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

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.

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

• By far the most elegant and really good use for BlankNullSequence! I found about it just last week and i was wondering how it can be used. Thanks!
– alex
Jul 21, 2020 at 22:07
• You are a godsend. Thank you so much. Jul 22, 2020 at 16:20

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

• Slightly simpler is: SequenceReplace[{1, 0, 1} -> Sequence[1, 1, 1]] /@ testlist Jul 21, 2020 at 0:25
• These are great! Really appreciate the help. Jul 22, 2020 at 16:21
list =
{{1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1}, {1, 0, 0, 1, 1, 1, 1, 0,1, 1, 1, 0}};


Using SequenceCases with Splice (new in 12.1)

SequenceCases[#, {a___, 1, 0, 1, b___} :> Splice[{a, 1, 1, 1, b}]] & /@ list


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

• (+1) Shorter: SequenceCases[list, {{a___, 1, 0, 1, b___}} :> {a, 1, 1, 1, b}] Feb 22 at 1:52
list = {{1, 1, 1, 0, 0, 0, 1, 1, 1, 0, 1, 1}, {1, 0, 0, 1, 1, 1, 1, 0, 1, 1, 1, 0}};


Using ReplaceList:

ReplaceList[list, {___, {a___, 1, 0, 1, b___}, ___} :> {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}}*)