3
$\begingroup$

This sounds simple and very likely a duplicate but I couldn't find an answer. Is there a quick functional way to split a list at certain values (multiple locations) while keeping those values in the subsists?

As an example:

seq1 = Range[10];
splitat1 = {1};
SequenceSplit[seq1, splitat1]

results in:

{{2, 3, 4, 5, 6, 7, 8, 9, 10}}

Here is my first problem, 1 is missing. Maybe I should be using a different method than SequenceSplit? Furthermore, what if I want to split at several locations? I tried this:

splitat2 = {{1}, {6}};
FlattenAt[SequenceSplit[seq1, #] & /@ splitat2, 1]

but obviously I am doing it wrong as I am splitting the list several times and then they repeat:

{{2, 3, 4, 5, 6, 7, 8, 9, 10}, {{1, 2, 3, 4, 5}, {7, 8, 9, 10}}}

How would I get this result?

{{1},{2, 3, 4, 5, 6}, {7, 8, 9, 10}}

Now having it split at the first element is a little bit harder probably, so even if there is chance splitting at {2,6} results in either

{{1,2},{3, 4, 5, 6}, {7, 8, 9, 10}}

or

{{1},{2, 3, 4, 5}, {6,7, 8, 9, 10}}

that would still solve my problem yet in a different way.

$\endgroup$
1
  • $\begingroup$ @HighPerformanceMark thanks, I couldn't get that to work yet. The criteria basically the split points are given as a list of members. $\endgroup$
    – MathX
    Mar 3, 2022 at 17:26

2 Answers 2

5
$\begingroup$

You can use Split:

Split[seq1, # != splitat1[[1]] &]
{{1}, {2, 3, 4, 5, 6, 7, 8, 9, 10}}
Split[seq1, # != 5 &]
{{1, 2, 3, 4, 5}, {6, 7, 8, 9, 10}}
Split[seq1, ! MatchQ[2 | 6] @ # &]
{{1, 2}, {3, 4, 5, 6}, {7, 8, 9, 10}}
Split[seq1, Nor[# == 2, # == 6] &]
{{1, 2}, {3, 4, 5, 6}, {7, 8, 9, 10}}
$\endgroup$
3
  • $\begingroup$ These are very promising, thanks! Is there a way I can construct the pattern to pass the split points as another list? let's say splitat= {2,5,7,9}? maybe MemberQ? $\endgroup$
    – MathX
    Mar 3, 2022 at 17:22
  • 1
    $\begingroup$ !MemberQ[{2,5,7,9},#]& or !MatchQ[Alternatives@@{2,5,7,9}]@#& should work. $\endgroup$
    – kglr
    Mar 3, 2022 at 17:28
  • $\begingroup$ This a great, thanks a lot! Split[seq1, ! MemberQ[splitat, #] &] works beautifully. $\endgroup$
    – MathX
    Mar 3, 2022 at 17:31
2
$\begingroup$

Let's say you have a list of numbers from 1-20 and you want to split it in sections given as follows:

alist = Range[20]
sections = {1, 5, 4, 6}

Use FoldPairList

FoldPairList[TakeDrop, alist, sections]

{{1}, {2, 3, 4, 5, 6}, {7, 8, 9, 10}, {11, 12, 13, 14, 15, 16}}


If you want the remaining part of the list as well:

FoldPairList[TakeDrop, alist, {Splice[sections], 
  Length@alist - Total@sections}]
{{1}, {2, 3, 4, 5, 6}, {7, 8, 9, 10}, {11, 12, 13, 14, 15, 16}, {17, 
  18, 19, 20}}
$\endgroup$
1
  • 1
    $\begingroup$ Thanks, this solution is nice too. I just converted my split element list to the sections as you have defined by sections = Prepend[Differences[splitat], First@splitat] and got the same results as @kglr solution. $\endgroup$
    – MathX
    Mar 3, 2022 at 17:58

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.