3
$\begingroup$

This question already has an answer here:

I am generating data such as {4,5,6,7,8,9,20,21,22,23,24,25,78,79,90}. This list can reach thousands of elements. Is there a simple or good method to convert such a list into a set on Interval objects which would be much shorter and manageable.

Thanks

$\endgroup$

marked as duplicate by Mr.Wizard list-manipulation Apr 8 '17 at 6:45

This question has been asked before and already has an answer. If those answers do not fully address your question, please ask a new question.

  • $\begingroup$ What is an interval object? $\endgroup$ – Igor Rivin Apr 8 '17 at 0:20
  • $\begingroup$ Mathematica has the function Interval[1,5] which is equivalent to {1,2,3,4,5} $\endgroup$ – Lorenz H Menke Apr 8 '17 at 0:25
  • $\begingroup$ According to the documentation it is NOT equivalent to that, but, rather, is the closed interval from $1$ to $5,$ so my question stands. Intervals do not appear to be the same as ranges... $\endgroup$ – Igor Rivin Apr 8 '17 at 0:28
  • $\begingroup$ Well yes they are not equivalent but the answer that I am looking for would from the example {Interval[4,9],Interval[20,25],Interval[78,79],Interval[90,90]}. I am not for this case interested in interval arithmetic just a representation. For the cases where there are thousands of elements the number of intervals would be about 10-20 which i much easier to analyze for my purpose. $\endgroup$ – Lorenz H Menke Apr 8 '17 at 0:39
2
$\begingroup$

how about this?

S = {4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25, 78, 79, 90};
consec = Most[#] == Rest[#] - 1 &;
DS = SequenceCases[S, {_, __}?consec];
Table[{First@DS[[i]], Last@DS[[i]]}, {i, 1, Length@DS}]

this one is better

S = {4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25, 78, 79, 90};
{Min[#], Max[#]} & /@ Split[S, #2 - #1 == 1 &]
$\endgroup$
  • $\begingroup$ Very nice, I was not at all thinking in this direction, however I note that it misses the last single case of 90. $\endgroup$ – Lorenz H Menke Apr 8 '17 at 0:55
  • $\begingroup$ yes... I guess there is a problem if you are having single cases... $\endgroup$ – J42161217 Apr 8 '17 at 1:07
  • $\begingroup$ Well, I can detect that and add it to the list afterwards. The solution is really neat. Thanks. $\endgroup$ – Lorenz H Menke Apr 8 '17 at 1:11
  • 1
    $\begingroup$ see this. list = {4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25, 78, 79, 90}; {Min[#], Max[#]} & /@ Split[list, #2 - #1 == 1 &] $\endgroup$ – J42161217 Apr 8 '17 at 1:12
  • $\begingroup$ See MinMax. $\endgroup$ – Edmund Apr 8 '17 at 1:44
0
$\begingroup$

Well, here is the simplest I can think of:

foo[l_, x_] := Module[{ll = l[[-1, -1]]},
  If[ll + 1 == x, Append[l[[;; -2]], Append[l[[-1]], x]],
   Append[l, {x}]]]

z[l_] := Fold[foo, {{l[[1]]}}, Rest[l]]

makeInt[l_] := int[#[[1]], #[[-1]]] & /@ z[l]

(notice that I am not using Interval, to avoid confusion.

$\endgroup$
0
$\begingroup$

You may use methods from Find continuous sequences inside a list, i.e. my intervals:

intervals[a_List] :=
 {a[[Prepend[# + 1, 1]]], a[[Append[#, -1]]]}\[Transpose] & @ 
  SparseArray[Differences @ a, Automatic, 1]["AdjacencyLists"]

intervals[{4, 5, 6, 7, 8, 9, 20, 21, 22, 23, 24, 25, 78, 79, 90}]

Interval @@ %

NumberLinePlot[%]
{{4, 9}, {20, 25}, {78, 79}, {90, 90}}

Interval[{4, 9}, {20, 25}, {78, 79}, {90, 90}]

enter image description here

$\endgroup$

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