# Creating sublists by rule

I would like to make a sublist consisting of the four elements that follow each occurrence of 1, 2 in the list:

lis = {a, b, 1, 2, c, d, e, f, g, 1, 2, w, x, y , z, q, r}


to make:

res = {{c, d, e, f}, {w, x, y, z}}


Thanks for any thoughts.

Cases[{2, p__} /; Length[{p}] >= 4 :> {p}[[;; 4]]] @
Rest @ Split[lis, {#, #2} =!= {1, 2} &]

{{c, d, e, f}, {w, x, y, z}}


And a variation:

Cases[{2, p__} /; Length[{p}] >= 4 :> Take[{p}, 4]] @
Rest @ Split[lis, {#, #2} =!= {1, 2} &]

{{c, d, e, f}, {w, x, y, z}}

• +1, but both solutions will fail in the cases like lis = {2, a, b, f, h, 1, 2, c, d, e, f};. Aug 29, 2021 at 7:45
• Thank you @AlexeyPopkov; good catch. Looks like wrapping Split with Rest fixes the issue.
– kglr
Aug 29, 2021 at 8:00
• Good idea with Rest! Probably more efficient version: Cases[{2, p : Repeated[_, {4}], ___} :> {p}]@Rest@Split[lis, {#, #2} =!= {1, 2} &]. Aug 29, 2021 at 8:45

An alternative solution to @TumbiSapichu's one:

SequenceCases[lis, {1, 2, p : Repeated[_, {4}]} :> {p}]
(* {{c, d, e, f}, {w, x, y, z}} *)


Something like this?

res = #[[-4 ;;]] & /@ SequenceCases[lis, {1, 2, _, _, _, _}]
(*{{c, d, e, f}, {w, x, y, z}}*)

(lis // SequencePosition[#,{1,2}][[All,2]]& // {1 + #,4 + #}&// Transpose)
// Map[Take[lis,#]&]

(* {{c, d, e, f}, {w, x, y, z}} * )

lis[[# + 1 ;; # + 4]] & /@ (#[[2]] & /@ SequencePosition[lis, {1, 2}])


Using Partition can assist in generating lists that have the correct length and need subsequent filtering only.

lis = {a, b, 1, 2, c, d, e, f, g, 1, 2, w, x, y, z, q, r};

Cases[Partition[lis, 6, 1], {1, 2, a__} :> {a}]


{{c, d, e, f}, {w, x, y, z}}

Consider a list (lis2) with an overlap and less than 4 characters after 1,2.

lis2 = {a, b, 1, 2, c, d, e, f, g, 1, 2, w, x, y, z, q, r, a, b, 1, 2, c, d, g, 1, 2, k, l, m, n, q, r};

Cases[Partition[lis2, 6, 1], {1, 2, a__} :> {a}]


{{c, d, e, f}, {w, x, y, z}, {c, d, g, 1}, {k, l, m, n}}

The third sublist can be filtered with an improved pattern that removes the overlap, if required.

Cases[Partition[lis2, 6, 1]
, {1, 2, b__ /; FreeQ[{b}, 1 | 2]} :> {b}]


{{c, d, e, f}, {w, x, y, z}, {k, l, m, n}}

• (+1) Nice, @Syed! Apr 3, 2023 at 18:45

Another way using Cases and SequenceSplit:

Cases[SequenceSplit[lis, Repeated[{1, 2}]], x_ /; Length[x] >= 4 :> x[[1 ;; 4]]]

{{c, d, e, f}, {w, x, y, z}}

list = {a, b, 1, 2, c, d, e, f, g, 1, 2, w, x, y, z, q, r};


Take[list, #] & /@