# If statement for Nested List

I am trying to use If function over a nested list below, to generate a new list that any element greater than 1 will be set to 0. Example list:

{{1, 2, 3}, {-0.1, 0.5, 0.9, 1.1, 2}, {2, 3, 0.3}}


Result:

{{0, 0, 0}, {-0.1, 0.5, 0.9, 0, 0}, {0, 0, 0.3}}


I thought this was simple, but I tried sth like fun[x_]:= If[x<1,x,0] and mapping it to the list, it turns out it cannot work on a nested list. Sorry if the question was asked, try to find a solution but failed!

lstlst = {{1, 2, 3}, {-0.1, 0.5, 0.9, 1.1, 2}, {2, 3, 0.3}}
lstlst /. {x_ /; x >= 1 -> 0}


or, if you really prefer to use Map with If, set the levelspec:

Map[If[# >= 1, 0, #] &, lstlst, {2}]

• Thank u very much! Dec 28, 2017 at 17:04
lst = {{1, 2, 3}, {-0.1, 0.5, 0.9, 1.1, 2}, {2, 3, 0.3}};

lst (1 - UnitStep[lst - 1])


{{0, 0, 0}, {-0.1, 0.5, 0.9, 0, 0}, {0, 0, 0.3}}

Alternatively, you can also Map your fun at Level {-1}:

fun[x_] := If[x < 1, x, 0]

Map[fun, lst, {-1}]


{{0, 0, 0}, {-0.1, 0.5, 0.9, 0, 0}, {0, 0, 0.3}}

One other solution to the problem is to use

sel = Function[x, If[x < 1, x, 0], Listable]


The function sel performs the comparison that is discussed in the body of the question (see Question) and returns the argument it is passed (ie x) when that is less than unity (and zero otherwise).

It also carries the Listable attribute ie it is automatically threaded over lists eg sel[{1,2,3}] returns {0,0,0} as expected. This behavior would not have been possible without Listable.

Now, applying the sel function on the input (ragged) list will produce the requested result. Please verify that evaluating

Apply[sel[{##}] &, lst, -1] == res


returns True, where lst={{1, 2, 3}, {-0.1, 0.5, 0.9, 1.1, 2}, {2, 3, 0.3}} is the input list and res={{0, 0, 0}, {-0.1, 0.5, 0.9, 0, 0}, {0, 0, 0.3}} is the desired output.

You could use Clip:

list = {{1,2,3}, {-0.1,0.5,0.9,1.1,2}, {2,3,0.3}};
Clip[
list,
{Min[list], 1-$MachineEpsilon}, {0,0} ]  {{0, 0, 0}, {-0.1, 0.5, 0.9, 0, 0}, {0, 0, 0.3}} Update Since there is a fair number of answers now, we can compare. Here is a dataset: data = RandomReal[2, {10^5,10}];  Here are the various answers: f1[data_] := data /. x_ /; x>=1 -> 0 (* Alan *) f2[data_] := Map[If[# >= 1, 0, #]&, data, {2}] (* Alan *) f3[data_] := Apply[Function[x, If[x<1, x, 0], Listable][{##}]&, data, -1] (* user42582 *) f4[data_] := data (1 - UnitStep[data - 1]) (* kglr *) f5[data_] := Map[If[# < 1, #, 0]&, data, {-1}] (* kglr *) f6[data_] := Clip[data, {Min[data], 1-$MachineEpsilon}, {0, 0}] (* Carl *)


Here is the comparison:

r1 = f1[data]; //RepeatedTiming
r2 = f2[data]; //RepeatedTiming
r3 = f3[data]; //RepeatedTiming
r4 = f4[data]; //RepeatedTiming
r5 = f5[data]; //RepeatedTiming
r6 = f6[data]; //RepeatedTiming

N @ r1 === N @ r2 === N @ r3 === N @ r4 === N @ r5 === N @ r6


{0.84, Null}

{0.9662, Null}

{1.42, Null}

{0.00706, Null}

{0.96, Null}

{0.0037, Null}

True

Summarizing, my answer is the fastest with @kglr's a close second. The others are about the same.

• Another variation using Clip: Clip[list, {-Infinity, 1}] //. {1 -> 0} Dec 28, 2017 at 20:37