# Remove singleton from Interval

I am using operations over Interval and the result of an intersection (or union) contains some singletons. Would it be possible to remove them ?

Example:

Interval[
{2894486400, 2894486400},
{2894659200, 2894832000},
{2895004800, 2895004800},
{2895177600, 2895350400}
]


Transformed in :

Interval[{2894659200, 2894832000}, {2895177600, 2895350400}]

• Try DeleteCases: DeleteCases[%, {$x_,$x_}] – kale Aug 5 '14 at 13:22
• Works well ! Is the variable $x_ a pattern ? I should learn that type of syntax :) – Mammouth Aug 5 '14 at 13:26 • Not necessarily. When matching patterns I just specified a variable x so that the first and last elements in the lists had to be the same. I usually add a $ so I don't get confused if another x has already been defined in my current context. – kale Aug 5 '14 at 13:31
• Thank you for the precision. I have not seen this very often, do you have any reference (book, article, etc.) that explains this ? – Mammouth Aug 5 '14 at 13:59
• Nope. Just a personal preference. I do the same thing for functions like FindRoot: $x /. FindRoot[Exp[$x]==5, {\$x,1}]. Like I said, complete personal preference. – kale Aug 5 '14 at 14:24

For version 10 you might use:

interval ~Select~ DuplicateFreeQ

Interval[{2894659200, 2894832000}, {2895177600, 2895350400}]


For other versions alternatives to DeleteCases include:

Select[interval, UnsameQ @@ # &]

Pick[#, UnsameQ @@@ #] & @ interval


### Benchmarks

As requested:

generate[n_] :=
Sort @ RandomInteger[n, ⌊.7n⌋] ~Partition~ 2 // Apply[Interval];

f1 = DeleteCases[{x_, x_}];
f2 = Select[DuplicateFreeQ];
f3 = Select[UnsameQ @@ # &];
f4 = Pick[#, UnsameQ @@@ #] &;
f5 = # /. {x_, x_} :> Sequence[] &;

Needs["GeneralUtilities"]

BenchmarkPlot[{f1, f2, f3, f4, f5}, generate, 2^Range[7, 16], "IncludeFits" -> True] The lines are hard to see here but:

• f1 and f4 are the winners with nearly identical timings
• f3 and f5 are the slowest
• f2 is in the middle
• All methods have the same complexity, unsurprisingly

If speed is the goal f5 can be improved by using Replace:

f6 = Replace[#, {x_, x_} :> Sequence[], {1}] &;

BenchmarkPlot[{f1, f5, f6}, generate, 2^Range[7, 16], "IncludeFits" -> True] This shows that DeleteCases has only the slightest performance margin over {x_, x_} :> Sequence[] when the latter is used with a targeted levelspec, which I find somewhat surprising as I assumed the latter would incur additional evaluation.

• Any advantage (speed, etc) of using one versus the others? I'm too lazy to test them lol. – seismatica Aug 5 '14 at 21:46
• @seismatica Let's find out. :-) – Mr.Wizard Aug 5 '14 at 22:05
• Very nice! +1.. – seismatica Aug 5 '14 at 22:21
• Could you add # /. {x_, x_} :> Sequence[] &? It's bound to be slower, but I'm curious :). – Teake Nutma Aug 6 '14 at 8:26
• @TeakeNutma Done. – Mr.Wizard Aug 6 '14 at 16:07

Yes, this is perfectly possible. In fact, there are multiple ways to do this. The most straightforward is to use DeleteCases, as @kale points out in the comments:

interval = Interval[
{2894486400, 2894486400},
{2894659200, 2894832000},
{2895004800, 2895004800},
{2895177600, 2895350400}
];

DeleteCases[interval, {x_, x_}]

Interval[{2894659200, 2894832000}, {2895177600, 2895350400}]


Here x_ is a named pattern. Because it occurs as {x_, x_}, it only matches those intervals that are singletons.

Another method, my favorite (but probably not as efficient as DeleteCases), is to replace the singletons with Sequence, which get automatically spliced out:

interval /. {x_, x_} -> Sequence[]

Interval[{2894659200, 2894832000}, {2895177600, 2895350400}]
`