# How do I replace elements in a list matching a pattern?

I have a list: {0, 1, 1, 1, 2, 2, 2, 6}. I want to replace all the elements that are greater than 1 with the integer 1. In other words, I want Mma to return the list {0,1,1,1,1,1,1,1,1}.

• Unitize[data] or Clip[data], maybe? Commented Mar 31, 2020 at 15:57
• lst = Table[RandomInteger[10], 10] Map[Min[#, 5] &, lst] 5 as an example. You should use 1. Commented Mar 31, 2020 at 16:13
• lst /. x_ /; x > 1 -> 1  Commented Mar 31, 2020 at 19:12

I just googled "wolfram mathematica replace if". Based on the first link I was able to figure it out in a minute!

lst = {0, 1, 1, 1, 2, 2, 2, 6};
lst /. {x_?(# > 1 &) -> 1}
{0, 1, 1, 1, 1, 1, 1, 1}


Usual approach would be to use ReplaceAll:

list = {0, 1, 1, 1, 2, 2, 2, 6};
list/.{x_?(# > 1 &) -> 1}


A slick approach would be

Boole /@ GreaterEqualThan[1] /@ list


Or even

Map[Min[#, 1] &, list]


Faster approach would be to use:

Unitize[list]
Clip[list]


All of them would give you:

{0, 1, 1, 1, 1, 1, 1, 1}


I just ran list = Table[RandomInteger[10], 100000] and used Mr.Wizard's timeAvg function:

list /. {x_?(# > 1 &) -> 1} // timeAvg
Boole /@ GreaterEqualThan[1] /@ list // timeAvg
Map[Min[#, 1] &, l] // timeAvg
Unitize[l] // timeAvg
Clip[l] // timeAvg


0.0690836

0.0559747

0.00204779

0.000139352

0.00022492

• Thank you, this is very helpful. Commented Mar 31, 2020 at 17:03
• @geoffrey, glad that was helpful. Commented Mar 31, 2020 at 17:13
lst = {0, 1, 1, 1, 2, 2, 2, 6};


Using SubsetMap:

p = Position[lst, n_ /; n > 1];

SubsetMap[Subtract @@ {#, #} + 1 &, #, p] &@lst


Result:

{0, 1, 1, 1, 1, 1, 1, 1}

Or using Cases:

Cases[lst, n_ :> If[n > 1, 1, n]]


Result:

{0, 1, 1, 1, 1, 1, 1, 1}

This is a long comment which wouldn't fit in the provided space, so here it goes. The conclusion is that good test data results in more general and compliant solutions.

-- TLDR

OP requires: to replace all the elements that are greater than 1 with the integer 1.

It is almost implied that list members are natural numbers and the answers conform to the provided data.

The documentation states that Unitize:

gives 0 when x is zero, and 1 when x has any other numerical value.

Hence in this context, negative numbers are also converted to 1 which is not desired. Also, a non-numerical value would remain unevaluated.

For a list that has elements with other Heads and Signs, a possible solution could be:

lst = {0, 1, 1.1, -2, 2, 2, 0.9, 6, a, 3 + 4 I, 1/2, 17/3};

Clear[g]
g[n_Real | n_Rational | n_Integer] :=
Clip[n, {-∞, 1}, {n, 1}]
g[n_] := n

{lst, Cases[lst, n_ :> g[n]]} // Grid


• (+1) An interesting observation, since the case you address is more general. Commented Feb 13 at 7:17
list = {0, 1, 1, 1, 2, 2, 2, 6};


1.

Using SequenceReplace (new in 11.3)

SequenceReplace[list, {Except @ 0} -> 1]


{0, 1, 1, 1, 1, 1, 1, 1}

2.

Some position-based solutions

p = Position[list, x_ /; x > 1]


{{5}, {6}, {7}, {8}}

MapAt[1 &, p] @ list;

ReplaceAt[_ :> 1, p] @ list;

ReplacePart[p -> 1] @ list;


All return

{0, 1, 1, 1, 1, 1, 1, 1}

list = {0, 1, 1, 1, 2, 2, 2, 6};


Using BoolEval by Szabolcs Horvát

BoolEval = ResourceFunction["BoolEval"];

BoolEval[list >= 1]


{0, 1, 1, 1, 1, 1, 1, 1}