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$
  • 1
    $\begingroup$ Related: (2952), (3412), (23607), (47296), (77796) $\endgroup$ – Mr.Wizard Jan 15 '16 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 '16 at 15:17
  • 1
    $\begingroup$ @JasonB Ok, I've adjusted the wording to take that into account :) $\endgroup$ – Kuba Jan 15 '16 at 15:21
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$
  • $\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 '16 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 '16 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 '16 at 14:29
5
$\begingroup$
Rest /@ Internal`PartitionRagged[list, 
   Flatten@Differences@Position[Append[list, {a}], {a}]] // Column

enter image description here

$\endgroup$
  • $\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 '16 at 15:34
  • $\begingroup$ mathematica.stackexchange.com/questions/805/… $\endgroup$ – eldo Jan 15 '16 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, privacy policy and cookie policy

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