I have a list which is something like this:
{3,4,5,6,7,10,11,12,15,16,17,19,20,21,22,23,24,42,43,44,45,46}
What I'd like to to is get the intervals which are in a "continuous" sequence, something like:
{{3,7},{10,12},{15,17},{19,24},{42,46}}
and get the extremes. Note that the original data (of which this is a small excerpt) shows no sign of regularity or repetition. Numbers start from 1 and get up to 200 (these numbers come from applying Position[] to an array).
Any pointers/ideas?
Answer
You can use Split in this simple case
list = {3, 4, 5, 6, 7, 10, 11, 12, 15, 16, 17, 19, 20, 21, 22, 23, 24, 42, 43, 44, 45, 46};
{Min[#], Max[#]} & /@ Split[list, #2 - #1 == 1 &]
What it does is that the last argument to split gives True only when neighboring elements have a difference of 1. If not, the list is split there. Then you can use the Min/Max approach to find the ends. First and Last will work too.
Update:
Since the attention to this question/answer is rather surprising, let me point out one important thing: It is the crucial difference between Split and SplitBy. Both functions take a second argument to supply a testing function to specify the point to split but the behavior is completely different. Btw, the same is true for Gather and GatherBy.
While the second argument to Split makes that it
treats pairs of adjacent elements as identical whenever applying the function test to them yields True,
SplitBy does a completely different thing. It
splits list a into sublists consisting of runs of successive elements that give the same value when f is applied.
If you weren't aware of this, a closer look is surely advisable.
Comments
Post a Comment