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

8 Answers 8

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$
3
$\begingroup$
(lis // SequencePosition[#,{1,2}][[All,2]]& // {1 + #,4 + #}&// Transpose) 
// Map[Take[lis,#]&]

(* {{c, d, e, f}, {w, x, y, z}} * )
$\endgroup$
3
$\begingroup$
lis[[# + 1 ;; # + 4]] & /@ (#[[2]] & /@ SequencePosition[lis, {1, 2}])
$\endgroup$
3
$\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, 2023 at 18:45
2
$\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$
1
$\begingroup$
list = {a, b, 1, 2, c, d, e, f, g, 1, 2, w, x, y, z, q, r};

A variant of 1066's answer:

Take[list, #] & /@
 Replace[SequencePosition[list, {1, 2}], {_, a_} :> {a + 1, a + 4}, {1}]

{{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 you have read our privacy policy.

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