# Subtract value from list

I want to subtract a constant value from a list and if the result is less than 0 then the corresponding list entry should be 0.

Here is my code:

list = {2, 3, 5, 4, 6, 7, 3, 7, 5, 4};

value = 5;

n = Length[list];

Do[
If[list[[i]] - value < 0, list[[i]] = 0];
, {i, 1, n}
]

list

{0, 0, 5, 0, 6, 7, 0, 7, 5, 0}

How would you solve this, without a loop?

I would use Clip:

Clip[{2,3,5,4,6,7,3,7,5,4}, {5, Infinity}, {0, 0}]

{0, 0, 5, 0, 6, 7, 0, 7, 5, 0}

You could also use Threshold

list = {2, 3, 5, 4, 6, 7, 3, 7, 5, 4};

value = 5;

For the case of integers

Threshold[list, value - 1]

(* {0, 0, 5, 0, 6, 7, 0, 7, 5, 0} *)

EDIT: Comparative timings

kumar[list_, value_] := UnitStep[list - value] list

hanlon[list_, value_] := Threshold[list, value - 1]

alan[list_, value_] := If[# < value, 0, #] & /@ list

woll[list_, value_] := Clip[list, {value, ∞}, {0, 0}]

nasser[list_, value_] :=
ReplacePart[list, Position[list, x_ /; x - value < 0] -> 0]

{#, RepeatedTiming[Do[temp = #[list, value], {10000}]; temp]} & /@ {hanlon,
woll, alan, kumar, nasser} // Grid

• Thanks a lot... also for the speed comparison.
– lio
Oct 18, 2017 at 4:53

Using UnitStep

UnitStep[list - value] list

{0, 0, 5, 0, 6, 7, 0, 7, 5, 0}

I like Anjan solution best. But here is another way

list={2,3,5,4,6,7,3,7,5,4};
value=5;
ReplacePart[list, Position[list,x_/;x-value<0]->0]

If you really want to replace the list items, then I would do

list[[Catenate@Position[list, x_ /; x < 5]]] = 0

However, if a new list is acceptable (and this is usually a better practice), then I would view this as a simple map:

If[# < 5, 0, #] & /@ list

This may work for you too:

list = {2, 3, 5, 4, 6, 7, 3, 7, 5, 4};
value = 5;
list /. x_ /; x < value :> 0

{0, 0, 5, 0, 6, 7, 0, 7, 5, 0}

Here's yet another one, a simple alternative to Threshold. It's slower than some of the other ones for integer input, but it's actually the fastest if your values are Reals:

f[list_, value_] := Chop[list, value]

Just to be clear, for integer input, you'd need use N@list and then convert the result back to an integer via some form of rounding, which slows down the function.

Running Bob's speedtest:

kumar[list_, value_] := UnitStep[list - value] list
hanlon[list_, value_] := Threshold[list, value - 1]
alan[list_, value_] := If[# < value, 0, #] & /@ list
woll[list_, value_] := Clip[list, {value, \[Infinity]}, {0, 0}]
nasser[list_, value_] := ReplacePart[list, Position[list, x_ /; x - value < 0] -> 0]
ender[list_, value_] := Chop[list, value]

list = N@{2, 3, 5, 4, 6, 7, 3, 7, 5, 4};
value = 5;

{#, RepeatedTiming[Do[temp = #[list, value], {10000}];
temp]} & /@ {hanlon, woll, alan, kumar, nasser, ender} // Grid

The integer variant clocks in at about half the speed of Bob's Threshold solution.

It's worth noting that this assumes that the values are all positive (because it would also keep values less than -value).

I tried to define a function an then map over lists

aaa = {2, 7, 6, 0, 11}

f[c_] := If[# - c > 0, # - c, 0] &

f[4] /@ aaa
{0, 3, 2, 0, 7}

Late to the party but mapping a function along your list is a robust strategy for replacing loops ie,

ls={2, 3, 5, 4, 6, 7, 3, 7, 5, 4};
f[n_]:=If[n-5<0,0,n];
f/@ls

It's not as terse as the pure functions but has some clarity for beginners, especially if they don't know a built-in function exists.