6
$\begingroup$

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.

$\endgroup$

7 Answers 7

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

An alternative solution to @TumbiSapichu's one:

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

Something like this?

res = #[[-4 ;;]] & /@ SequenceCases[lis, {1, 2, _, _, _, _}]
(*{{c, d, e, f}, {w, x, y, z}}*)
$\endgroup$
2
$\begingroup$
(lis // SequencePosition[#,{1,2}][[All,2]]& // {1 + #,4 + #}&// Transpose) 
// Map[Take[lis,#]&]

(* {{c, d, e, f}, {w, x, y, z}} * )
$\endgroup$
2
$\begingroup$
lis[[# + 1 ;; # + 4]] & /@ (#[[2]] & /@ SequencePosition[lis, {1, 2}])
$\endgroup$
2
$\begingroup$

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

$\endgroup$
1
  • 1
    $\begingroup$ (+1) Nice, @Syed! $\endgroup$ Apr 3 at 18:45
1
$\begingroup$

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}}
$\endgroup$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge that you have read and understand our privacy policy and code of conduct.

Not the answer you're looking for? Browse other questions tagged or ask your own question.