5
$\begingroup$

How do I replace all occurrences of -1,1 with 0,1 in a list

example:

list = {-1, 1, -1, 1, 1, 1, -1, -1, -1, 1} 

desired output:

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

I tried the following:

list/.{x___, -1, 1, y___} -> {x, 0, 1, y} 

However, this only matches the first instance of the pattern. A working solution I found is this:

list//.{x___, -1, 1, y___} -> {x, 0, 1, y} 

This scales atrociously though.

$\endgroup$
6
  • $\begingroup$ SequenceReplace[list, {-1, 1} -> Sequence[0, 1]]? $\endgroup$ Commented May 18, 2020 at 16:00
  • $\begingroup$ My version does not seem to support SequenceReplace $\endgroup$ Commented May 18, 2020 at 16:07
  • $\begingroup$ @MarcoB I am sorry for that, I saw your comment after I posted with a very similar answer. $\endgroup$ Commented May 18, 2020 at 16:10
  • 1
    $\begingroup$ @braaterAfrikaaner I see. Could you add which version you are using to your question? $\endgroup$ Commented May 18, 2020 at 17:48
  • 1
    $\begingroup$ @braaterAfrikaaner I am confused why the accepted answer uses the function that your version, which you do not list, does not support? Can you please clarify this? $\endgroup$ Commented May 18, 2020 at 18:01

3 Answers 3

7
$\begingroup$

This seems to work.

bill = {-1, 1, -1, 1, 1, 1, -1, -1, -1, 1}; Flatten[SequenceReplace[bill, {-1, 1} :> {0, 1}]] 

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

I also include the output without Flatten, it might be of interest as to how it works. The documentation can be found here

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

EDIT: Courtesy of @MarcoB and @Bob Hanlon:

 SequenceReplace[bill, {-1, 1} :> Sequence[0, 1]] 
$\endgroup$
4
  • 2
    $\begingroup$ Also SequenceReplace[bill, {-1, 1} :> Sequence[0, 1]] $\endgroup$ Commented May 18, 2020 at 16:24
  • 1
    $\begingroup$ what's the reason for RuleDelayed and not Rule? there is no need to evaluate Sequence each time it is replaced, am i wrong? $\endgroup$ Commented May 18, 2020 at 16:57
  • $\begingroup$ I posted a solution that is faster with a shorter Trace and does not use SequenceReplace (which is the obvious choice if it is applicable). $\endgroup$ Commented May 18, 2020 at 18:27
  • $\begingroup$ In version 12.1, SequenceReplace[bill, {-1, 1} :> Splice[{0, 1}]] $\endgroup$ Commented May 24, 2020 at 14:23
5
$\begingroup$

This is the solution I came up with. It should work with 10.1+

 ReplacePart[list, Rule[#, 0] & /@ First /@ SequencePosition[list, {-1, 1}]] (* {0, 1, 0, 1, 1, 1, -1, -1, 0, 1} *) 

The length of the Trace is 4. Oddly, considering its messy implementation, this is shorter than the length of the Trace for the solution in Titus's answer, which is 5.

 Length@Trace@ ReplacePart[list, Rule[#, 0] & /@ First /@ SequencePosition[list, {-1, 1}]] Length@Trace@SequenceReplace[list, {-1, 1} :> Sequence[0, 1]] (* 4 *) (* 5 *) 

The solution is also somehow faster, this might be given due to the shorter length of the Trace. That would mean that it scales better than that of Titus's solution.

 ReplacePart[list, Rule[#, 0] & /@ First /@ SequencePosition[list, {-1, 1}]] // RepeatedTiming // First SequenceReplace[list, {-1, 1} :> Sequence[0, 1]] // RepeatedTiming // First (* 0.000034 *) (* 0.000078 *) 

Hope you find that this helps for the version that you are on.

$\endgroup$
3
$\begingroup$
Join[ #[[;; -2, 1]], # [[-1]] ] &@ (Partition[list, 2, 1, {1, 2}] /. {-1, 1} -> {0, 1}) 
$\endgroup$
1
  • $\begingroup$ @SubaThomas no it fails at the last element $\endgroup$ Commented May 18, 2020 at 17:03

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.