TransWikia.com

How do I replace specific sequences of a sublist without changing the level of the list?

Mathematica Asked by KyCygni on August 22, 2021

Suppose I have a list of multiple sublists:

testlist={{1,1,1,0,0,0,1,1,1,0,1,1},{1,0,0,1,1,1,1,0,1,1,1,0}}

I want to replace given sequences without creating new sublists and without flattening.

For example, I’d like to replace all instances of {1,0,1} within all sublists with {1,1,1}.
The final output for the above should be:

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

Here are some attempts to show the issue:

testlist = {{1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1}, {1, 0, 0, 1, 1, 1, 
   1, 0, 1, 1, 1, 0}}
Replace[testlist, {1, 0, 1} :> {1, 1, 
   1}, {2}]; (* This does nothing; Replace doesn't accept sequences *)


Replace[testlist, 
 1 :> {2, 2}, {2}] (* Even if it did work, Replace creats new 
sublists *)
(* Output: 
{{{2,2},{2,2},{2,2},0,0,0,{2,2},{2,2},{2,2},0,{2,2},{2,2}},{{2,2},0,0,
{2,2},{2,2},{2,2},{2,2},0,{2,2},{2,2},{2,2},0}} *)

ReplaceAll[{1, 0, 1} -> {1, 1, 1}][testlist];
testlist /. {{1, 0, 1} -> {1, 1, 
    1}}; (* These two both do nothing: same reason *)
testlist //. 0 -> 2 (* This works as you'd expect *)
(* Output: {{1,1,1,2,2,2,1,1,1,2,1,1},{1,2,2,1,1,1,1,2,1,1,1,2}} *)
testlist //. {Sequence[1, 0, 1] -> 
   Sequence[1, 1, 1]}; (* This does nothing *)

f1[x_List] := 2*x
f1@testlist[[All]] (*This works as you'd expect*)
(* Output: {{2,2,2,0,0,0,2,2,2,0,2,2},{2,0,0,2,2,2,2,0,2,2,2,0}} *)
f2[x_List] := SequenceReplace[x, {1, 0, 1} -> Sequence[1, 1, 1]]
f2@testlist[[All]]; (*This does nothing*)
f2 @@@ testlist (* This doesn't work *)
(* Output: {f2[1,1,1,0,0,0,1,1,1,0,1,1],f2[1,0,0,1,1,1,1,0,1,1,1,0]} *)


SequenceReplace[
 Flatten@testlist, {1, 0, 1} -> 
  Sequence[1, 1, 1]] (* This works provided there are no sublists *)
(* Output: {1,1,1,0,0,0,1,1,1,1,1,1,1,0,0,1,1,1,1,1,1,1,1,0} *)

testlist /. {1 -> 
   Sequence @@ {2, 
     2}}(* This works and makes a replacement within the desired 
sublists *)
(* Output: 
{{2,2,2,2,2,2,0,0,0,2,2,2,2,2,2,0,2,2,2,2},{2,2,0,0,2,2,2,2,2,2,2,2,0,
2,2,2,2,2,2,0}} *)
testlist /. {Sequence[1, 0, 1] -> 
   Sequence @@ {1, 1, 1}} (* This does nothing *)

This feels like it should be simple, but all the documentation I can find only provides solutions for single lists, not sublists, and everything I find that says "You can do this for any level you want" doesn’t work for sequences.

I can force the answer with a For loop, but I’d like to extend this code to lists with thousands of numbers, and then run it for multiple lists, which doesn’t have acceptable scaling.

2 Answers

You can use pattern matching with BlankNullSequence

testlist //. {List[a___,1,0,1,b___] :> List[a,1,1,1,b]}
{{1, 1, 1, 0, 0, 0, 1, 1, 1, 1, 1, 1}, {1, 0, 0, 1, 1, 1, 1, 1, 1, 1, 1, 0}}

Correct answer by Hausdorff on August 22, 2021

Another way

SequenceReplace[{1, 0, 1} -> {1, 1, 1}] /* Flatten /@ testlist

Inspired by @carl woll's comment

SequenceReplace[{1, 0, 1} -> Splice[{1, 1, 1}]] /@ testlist

Answered by Rohit Namjoshi on August 22, 2021

Add your own answers!

Ask a Question

Get help from others!

© 2024 TransWikia.com. All rights reserved. Sites we Love: PCI Database, UKBizDB, Menu Kuliner, Sharing RPP