I have a long flat list that needs to be partitioned. The list is formatted so the "header" is repeated, followed by the values. Essentially, it looks something like this:

list={a,a,1,2,3,b,b,5,6,c,c,1,5,a,a,7,8,9,1}

I am looking for an output of:

{{a,1,2,3},{b,5,6},{c,1,5},{a,7,8,9,1}}

The output above would then let me create the association list I need.

Obviously Partition won't work because the sublists are of different lengths. I have looked at various ways to identify where the repeated "header" data is, but that doesn't help with the splits.

  • What is the header data? Is it symbols? Or a string? Or also numbers? – Henrik Schumacher Sep 21 at 14:53
  • In the actual data, all items would be treated as strings – kickert Sep 21 at 14:56
  • 1
    Should the list be split any duplicate or are there some known header strings? – Henrik Schumacher Sep 21 at 14:59
  • All headers will repeat and none of the following values will repeat. There is a chance that sets will have the same headers. Essentially, anytime a value is equal to the value before it, it can be used as the split point. – kickert Sep 21 at 15:10
up vote 8 down vote accepted
Join[Most /@ Rest @ Most @ #, {Last @ #}] & @ Split[list, UnsameQ]

{{a, 1, 2, 3}, {b, 5, 6}, {c, 1, 5}, {a, 7, 8, 9, 1}}

You can also use use Split twice and reorganize the result:

Rest /@ Flatten /@ Split[Split[list], Length @ #2 == 1 &]

{{a, 1, 2, 3}, {b, 5, 6}, {c, 1, 5}, {a, 7, 8, 9, 1}}

And yet an alternative way:

Take[list, {#, #2 - 2}] & @@@ 
 Partition[Last /@ SequencePosition[list, {a_, a_}], 2, 1, 1, {Length[list] + 2}] 

{{a, 1, 2, 3}, {b, 5, 6}, {c, 1, 5}, {a, 7, 8, 9, 1}}

  • That seems to have done it. Let me dig into the final output to see if there is any trickery going on. – kickert Sep 21 at 15:11
  • Okay, I think I am following. Normally Split puts all the same repeated elements together, but by specifying that UnsameQ you are grouping things that are dissimilar. That makes sense. Then by mapping Most you are dropping the last element of each sublist. I am not quite sure I understand what you are doing with the the Replace all and SlotSequence. Obviously the first list will be invalid, but couldn't you just use Rest[Most /@ Split[list, UnsameQ]] Thanks for the guidance! – kickert Sep 21 at 17:25
  • 1
    @kickert, the original answer was incorrect. Fixed now. Thank you for the accept. – kglr Sep 21 at 18:25
  • Right or wrong, all your solutions got me where I needed to be. – kickert Sep 21 at 18:44
SequenceSplit[list, {a_, a_, x:_Integer ..} -> {a,x}]

{{a, 1, 2, 3}, {b, 5, 6}, {c, 1, 5}, {a, 7, 8, 9, 1}}

Your Answer

 
discard

By clicking "Post Your Answer", you acknowledge that you have read our updated terms of service, privacy policy and cookie policy, and that your continued use of the website is subject to these policies.

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