19
$\begingroup$

Say I have the list

{{a}, {0, 2, 5}, {5, 4, 1}, {a}, {1, 1, 0}, {1, 4, 2}, 
 {3, 3, 0}, {a}, {3, 2, 0}, {1, 4, 1}}

I would like to make sublists of everything beginning with the {a} element till the next {a} or the and of the list.

Either

{{{0, 2, 5}, {5, 4, 1}},
 {{1, 1, 0}, {1, 4, 2}, {3, 3, 0}},
 {{3, 2, 0}, {1, 4, 1}}}

or

{{{a},{0, 2, 5}, {5, 4, 1}},
 {{a},{1, 1, 0}, {1, 4, 2}, {3, 3, 0}},
 {{a},{3, 2, 0}, {1, 4, 1}}}

would be acceptable. I'm sure there is a duplicate, but I can't find the easiest way to do this (that isn't a clunky While loop with an AppendTo)

$\endgroup$
3
  • 1
    $\begingroup$ Related: (2952), (3412), (23607), (47296), (77796) $\endgroup$
    – Mr.Wizard
    Jan 15, 2016 at 15:04
  • 1
    $\begingroup$ @Kuba - in the actual job I'm doing, I'm trying to get molecule geometries from a large text file where they are always preceded by a line that is like "----------------------". I can probably do it better with some combination of grep and awk, but I can never figure out awk. $\endgroup$
    – Jason B.
    Jan 15, 2016 at 15:17
  • 1
    $\begingroup$ @JasonB Ok, I've adjusted the wording to take that into account :) $\endgroup$
    – Kuba
    Jan 15, 2016 at 15:21

4 Answers 4

26
$\begingroup$
Split[list, (#2 =!= {a}) &]
{
 {{a}, {0, 2, 5}, {5, 4, 1}},
 {{a}, {1, 1, 0}, {1, 4, 2}, {3, 3, 0}}, 
 {{a}, {3, 2, 0}, {1, 4, 1}}
}

If you add Map@Rest you will get the first form.

Alternatively, for V10.2+ users:

SequenceCases[list, {{a}, Except[{a}] ...}]

or

SequenceCases[list, {{a}, Longest[___]}]
$\endgroup$
3
  • $\begingroup$ This is great. Can you tell me what the practical difference is between != and =!= are? Either one seems to give the same result for your code. Perhaps when only comparing two things there is no difference? Or it's similar to the difference between SameQ and Equal $\endgroup$
    – Jason B.
    Jan 15, 2016 at 14:20
  • $\begingroup$ Answered my question there, via this blog post: "If you are not sure if someone gives a variable or a value you can use =!= to force a true or false" $\endgroup$
    – Jason B.
    Jan 15, 2016 at 14:24
  • $\begingroup$ @JasonB :) so you know. But that's not so easy, maybe you want 1 to be 1. then == gives true and === false. $\endgroup$
    – Kuba
    Jan 15, 2016 at 14:29
5
$\begingroup$
Rest /@ Internal`PartitionRagged[list, 
   Flatten@Differences@Position[Append[list, {a}], {a}]] // Column

enter image description here

$\endgroup$
2
  • $\begingroup$ Nice, I was trying something like Span@Partition@Position..... but I like PartitionRagged better. Where are all these undocumented functions listed? Are they in a staging area for the next version? :-) $\endgroup$
    – Jason B.
    Jan 15, 2016 at 15:34
  • $\begingroup$ mathematica.stackexchange.com/questions/805/… $\endgroup$
    – eldo
    Jan 15, 2016 at 15:37
5
$\begingroup$
SplitBy[l, FreeQ[{##}, a] &] /. {{a}} :> Sequence[]

Or

Level[Nest[
   MapAt[TakeDrop[#, First@FirstPosition[#, {a}]] &, 
     Level[#, {-3}], -1] &, {l}, 
   Length[Position[l, {a}]]], {-3}] //. {a} | {} -> Sequence[]
$\endgroup$
2
$\begingroup$
Join @@@ Partition[SplitBy[list, MemberQ[{{a}}, #] &], 2]

{{{a}, {0, 2, 5}, {5, 4, 1}}, {{a}, {1, 1, 0}, {1, 4, 2}, {3, 3, 0}}, {{a}, {3, 2, 0}, {1, 4, 1}}}

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