6
$\begingroup$

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}.

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

6 Answers 6

5
$\begingroup$

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}
$\endgroup$
7
$\begingroup$

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

$\endgroup$
2
  • 2
    $\begingroup$ Thank you, this is very helpful. $\endgroup$
    – geoffrey
    Commented Mar 31, 2020 at 17:03
  • $\begingroup$ @geoffrey, glad that was helpful. $\endgroup$ Commented Mar 31, 2020 at 17:13
3
$\begingroup$
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}

$\endgroup$
3
$\begingroup$

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

enter image description here

$\endgroup$
1
  • $\begingroup$ (+1) An interesting observation, since the case you address is more general. $\endgroup$ Commented Feb 13 at 7:17
2
$\begingroup$
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}

$\endgroup$
2
$\begingroup$
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}

$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Not the answer you're looking for? Browse other questions tagged or ask your own question.