Splitting a list by specifying section headers
Here's my suggestion:
mylist = {"[a]", "a", "a", "[b]", "b", "b", "[ c ]", "c", "c"};
Split[mylist, ! StringMatchQ[#2, "[*"] &]
and we get:
{{"[a]", "a", "a"}, {"[b]", "b", "b"}, {"[ c ]", "c", "c"}}
At the risk of being annoying, I will pitch the linked lists again. Here is the code using linked lists:
ClearAll[split];
split[{}] = {};
split[l_List] :=
Reap[split[{}, Fold[{#2, #1} &, {}, Reverse@l]]][[2, 1]];
split[accum_, {h_, tail : {_?sectionQ, _} | {}}] :=
split[Sow[Flatten[{accum, h}]]; {}, tail];
split[accum_, {h_, tail_}] := split[{accum, h}, tail];
The function sectionQ
has been stolen from the answer of @rm-rf. The usage is
split[mylist]
(* {{[a],a,a},{[b],b,b},{[ c ],c,c}} *)
The advantages I see in using linked lists is that they allow one to produce solutions which are
- Easily generalizable to more complex problems
- Straightforward to implement
- Easy to argue about (in terms of algorithmic complexity etc)
They may not be the fastest though, so may not always be suitable for performance-critical applications.
Here's one method, using a slightly modified example:
mylist = {"[a]", "a", "[b]", "b", "b", "b", "[ c ]", "c", "c"};
pos = Append[Flatten[Position[mylist,
s_String /; StringMatchQ[s, "[" ~~ ___]]], Length[mylist] + 1]
{1, 3, 7, 10}
Take[mylist, {#1, #2 - 1}] & @@@ Partition[pos, 2, 1]
{{"[a]", "a"}, {"[b]", "b", "b", "b"}, {"[ c ]", "c", "c"}}