7
$\begingroup$

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.

$\endgroup$
4
  • $\begingroup$ What is the header data? Is it symbols? Or a string? Or also numbers? $\endgroup$ Commented Sep 21, 2018 at 14:53
  • $\begingroup$ In the actual data, all items would be treated as strings $\endgroup$
    – kickert
    Commented Sep 21, 2018 at 14:56
  • 1
    $\begingroup$ Should the list be split any duplicate or are there some known header strings? $\endgroup$ Commented Sep 21, 2018 at 14:59
  • $\begingroup$ 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. $\endgroup$
    – kickert
    Commented Sep 21, 2018 at 15:10

4 Answers 4

9
$\begingroup$
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}}

$\endgroup$
4
  • $\begingroup$ That seems to have done it. Let me dig into the final output to see if there is any trickery going on. $\endgroup$
    – kickert
    Commented Sep 21, 2018 at 15:11
  • $\begingroup$ 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! $\endgroup$
    – kickert
    Commented Sep 21, 2018 at 17:25
  • 1
    $\begingroup$ @kickert, the original answer was incorrect. Fixed now. Thank you for the accept. $\endgroup$
    – kglr
    Commented Sep 21, 2018 at 18:25
  • $\begingroup$ Right or wrong, all your solutions got me where I needed to be. $\endgroup$
    – kickert
    Commented Sep 21, 2018 at 18:44
8
$\begingroup$
SequenceSplit[list, {a_, a_, x:_Integer ..} -> {a,x}]

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

$\endgroup$
1
$\begingroup$
Split[
   DeleteAdjacentDuplicates[list, MatchQ[#1, _Symbol] && MatchQ[#2, _Symbol] &], 
IntegerQ[#2] &]

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

$\endgroup$
1
$\begingroup$
list={a,a,1,2,3,b,b,5,6,c,c,1,5,a,a,7,8,9,1};

Split[list, Head[#1] == Symbol || Head[#2] == Integer &] // Map[Rest]

{{a, 1, 2, 3}, {b, 5, 6}, {c, 1, 5}, {a, 7, 8, 9, 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.