8
$\begingroup$

Consider the following list:

{"END", "END", "a", "b", "END", "p", "q", "END", "t", "END"}

I want to combine elements that precede the marker element "END"; I also wish to include the marker with the combined elements. Here's the desired output:

{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}

I'm looking for an elegant way of performing this using Mathematica's in built functions, without needing to use procedural programming (though it would be easy to do so).

Here's a way of doing it that doesn't quite work, due to it not handling the two consecutive markers at the start. Even if it does work, I'm not sure if it would be very efficient or elegant:

Flatten /@ 
 SequenceCases[
  SplitBy[{"END", "END", "a", "b", "END", "p", "q", "END", "t", 
    "END"}, # === "END" &], {_, {"END"}}]

(* Outputs: {{"a","b","END"},{"p","q","END"},{"t","END"}} *)
$\endgroup$

3 Answers 3

9
$\begingroup$
Split[list, # != "END" &]

{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}

Also

SequenceReplace[list, {a : Except["END"] ..., "END"} :> {a, "END"}]

{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}

and

TakeList[#, 
   Differences[
    Union @@ Join[{{0}}, Position[#, "END"], {{ Length@#}}]]] &@list

{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}

$\endgroup$
1
$\begingroup$
list = {"END", "END", "a", "b", "END", "p", "q", "END", "t", "END"};

Using SequenceSplit (new in 11.3)

SequenceSplit[list, x : {Except["END"] ..., "END"} :> x]

{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}

$\endgroup$
1
$\begingroup$
list = {"END", "END", "a", "b", "END", "p", "q", "END", "t", "END"};

Using SequenceCases:

SequenceCases[list, s : {Except["END"] ..., "END"} :> s]

(*{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}*)

Or using Take and SequencePosition:

SequencePosition[list, {Except["END"] ..., "END"}, Overlaps -> False]

Take[list, #] & /@ %

(*{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}*)

Or using Position, Partition and Take:

Join @@ {{First@#}, #} &@Partition[Flatten@Position[list, "END"], 2, 1]

Rest@Take[list, #] & /@ %

(*{{"END"}, {"END"}, {"a", "b", "END"}, {"p", "q", "END"}, {"t", "END"}}*)
$\endgroup$

Your Answer

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