6
$\begingroup$

I want to replace all instances of 0 in the outer most level of a nested list with 1. However, when I use ReplaceAll as

ReplaceAll[{{0, 0}, 0}, 0 -> 1]

it replaces all three zeros, rather than just the last one. What should I do to only replace the zeros in the outermost level? I will be using this on a much longer nested list so I don't want to refer to the specific positions of individual zeros.

Thanks in advance for any help.

$\endgroup$

4 Answers 4

3
$\begingroup$

Try

 Replace[{{0, 0}, 0}, 0 -> 1, {1}]
$\endgroup$
2
  • 1
    $\begingroup$ What is the difference between this (levelspec as {1}) and the answer I proposed (levelspec as 1)? $\endgroup$
    – a20
    Dec 9, 2021 at 14:33
  • $\begingroup$ Not much of a difference. Sorry, I overlooked, that your answer included Replace, already. $\endgroup$
    – dnet
    Dec 10, 2021 at 15:15
8
$\begingroup$

I am sure there are a hundred other solutions, but this one does the job and should be reasonably efficient:

In: Map[If[ListQ[#], #, Replace[#, 0 -> 1]] &, {{0, 0}, 0}]
Out: {{0,0},1}

Another better solution:

In: Replace[{{0, 0}, 0, 0, 0, {0, 0, 0}, {{0, 0}, 0}, 0, 0}, 0 -> 1, 1]
Out: {{0, 0}, 1, 1, 1, {0, 0, 0}, {{0, 0}, 0}, 1, 1}

The final '1' in the Replace[] expression indicates the level to act on. If you change it to '2' you instead get:

In: Replace[{{0, 0}, 0, 0, 0, {0, 0, 0}, {{0, 0}, 0}, 0, 0}, 0 -> 1, 2]
Out: {{1, 1}, 1, 1, 1, {1, 1, 1}, {{0, 0}, 1}, 1, 1}

EDIT

A word of caution on the solution using Replace[], this will only work if all elements with zeros that you want to replace only contain zeros. Say that you want to replace 'x' in the following:

In: Replace[{x, x + a, {x}}, x -> 1, 1]
Out: {1, a + x, {x}}

you see that the 'x' in the second element was not replaced. This is because it is at level 2, and not level 1. A possible solution to this is to use the Map[] as follows:

In: Map[If[ListQ[#], #, Replace[#, x -> 1, All]] &, {x, x + a, {x}}]
Out: {1, 1 + a, {x}}

note the 'All' at the level specification for Replace here. This means that 'x' on any level will be replaced, but only if the element is not a list.

Once again, there is probably a neater solution here to this more general case. Maybe someone else has a suggestion.

$\endgroup$
1
$\begingroup$
list = {{0, 0}, 0, 0, 0, {0, 0, 0}, {{0, 0}, 0}, 0, 0};

Using SequenceReplace (new in 11.3)

SequenceReplace[list, {0} :> 1]

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

Using ReplaceAt (new in 13.1)

ReplaceAt[list, _ :> 1, Position[list, 0, 1]]

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

$\endgroup$
1
$\begingroup$
list = {{0, 0}, 0, 0, 0, {0, 0, 0}, {{0, 0}, 0}, 0, 0};

Grabbing the @eldo's list and using SubsetMap:

SubsetMap[# + 1 &, list, Position[list, 0, 1]]

(*{{0, 0}, 1, 1, 1, {0, 0, 0}, {{0, 0}, 0}, 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.