5
$\begingroup$

I have a list in which the first index is mostly increasing, but dips sometimes.

I need to split this list in two or more lists in this way: when the first element of a pair is smaller than the preceding first element, I need to split the list and create new separate lists.

This is an explanatory example:

list = {{1, 10}, {2, 20}, {3, 30}, {4, 40}, {5,50},
        {2, 20}, {3, 30}, {4, 40}, {5, 50}, {1, 10}, {2, 20}, {4, 40}};

newlist1 = {{1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}};
newlist2 = {{2, 20} {3, 30} {4, 40} {5, 50}};
newlist3 = {{1, 10}, {2, 20}, {4, 40}};
$\endgroup$
  • $\begingroup$ I formatted and rephrased your question and the title slightly to make it more accessible. $\endgroup$ – Yves Klett Jul 31 '13 at 17:38
11
$\begingroup$

It's very easy :

 list = {{1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {2, 20}, {3, 
        30}, {4, 40} , {5, 50}, {1, 10}, {2, 20}, {4, 40}};

 Split[list, #1[[1]] < #2[[1]] &] 

{
{{1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}},
{{2, 20}, {3, 30}, {4,40}, {5, 50}},
{{1, 10}, {2, 20}, {4, 40}}
}

$\endgroup$
  • 2
    $\begingroup$ @Mary note Split can be highly abused and can do amazing things, if you can figure out what the splitting function needs to be. Here's everything that references Split on this site. It is worthwhile looking through. $\endgroup$ – rcollyer Jul 31 '13 at 17:19
  • $\begingroup$ I think this should be <= rather than < based on my reading of the question. $\endgroup$ – Mr.Wizard Jul 31 '13 at 19:26
  • 1
    $\begingroup$ @rcollyer A better search might be restricted to code. $\endgroup$ – Mr.Wizard Jul 31 '13 at 21:41
  • $\begingroup$ @Mr.Wizard I did not know you could do that; show off. :) $\endgroup$ – rcollyer Jul 31 '13 at 22:58
  • $\begingroup$ @andre Thanks very easy solution! $\endgroup$ – Mary Aug 1 '13 at 6:52
5
$\begingroup$

Here is a function that is several times faster than Split:

runs[a_List] := Inner[a[[# ;; #2]] &, Prepend[# + 1, 1], Append[#, -1], List] & @
  SparseArray[UnitStep @ Differences @ a[[All, 1]], Automatic, 1]["AdjacencyLists"]

Test:

list = {{1, 10}, {2, 20}, {3, 30}, {4, 40}, {5, 50}, {2, 20}, {3, 30}, {4, 40},
        {5, 50}, {1, 10}, {2, 20}, {4, 40}};

runs[list] // Column
{{1,10},{2,20},{3,30},{4,40},{5,50}}
{{2,20},{3,30},{4,40},{5,50}}
{{1,10},{2,20},{4,40}}
big = Join @@ ConstantArray[list, 100000];

runs[big]                        // Timing // First
Split[big, #1[[1]] <= #2[[1]] &] // Timing // First

0.234

0.78


Related:
- Conditional Gathering of lists
- Find continuous sequences inside a list

$\endgroup$
  • 2
    $\begingroup$ not something for the casual debugger, though :-) $\endgroup$ – Yves Klett Jul 31 '13 at 19:40
  • $\begingroup$ @Mr.Wizard very smart solution! $\endgroup$ – Mary Aug 1 '13 at 6:54
  • $\begingroup$ @Mary Thanks; glad you like it. The SparseArray thing is fairly esoteric (and AFAIK undocumented). There are other examples of the use of SparseArray Properties in the second linked post at the bottom of this answer. $\endgroup$ – Mr.Wizard Aug 1 '13 at 15:22

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.