1

Assuming I have lots of time periods identified by starting and ending timestamp. What would be the quickest way to detect wich period overlaps on wich periods ?

Here an example :

Periods

9 different periods, delimited by a starting (from) and ending (to) timestamp.

A = [ from : 7s , to : 11s]
B = [ from : 1s, to : 8s]
C = [ from : 9s, to : 12s]
D = [ from : 4s, to : 7s]
E = [ from 10s, to: 15s]
F = [ from 0s, to : 5s]
G (oops i skipped it when drawing the image!)
H = [ from: 5s, to: 9s]
I = [ from: 11s, to: 13s]
J = [ from: 7s, to: 14s]

How to retreive all overlapping periods as quick as possible to get the following result ?

[[A,B],[A,C],[A,E],[A,H],[A,J],[B,D],[B,F],[B,H],[B,J],[C,E],[C,I],[C,J],[D,F],[D,H],[D,J],[E,I],[E,J],[H,J],[I,J]]

JSFiddle of my own solution here

And an other similar jsfiddle but this time with real timestamps, from january to march 2017 between 8 am to 18 pm EDT, and there is a lot of them.

JSFiddle with lots of timestamps

If someone can find a quicker way to proceed, that would be great ! Each milliseconds is precious for me hehe ;)

Simmoniz
  • 1,022
  • 14
  • 24

2 Answers2

2

Sort all the times together, marking each one with the segment it belongs to, and a start/end bit.

Then, keep a list saying which segments you are in (initially empty).

Iterate through the list of times. If a time belongs to segment X, then if it is a start time add X to the second list. If it is an end time, remove X from the second list. At all times the second list tells you which segments are overlapping.

If there are enough segments to care about big-O, the initial sort is O(N Log N). The iteration is O(N).

Of course, don't count on big-O to make you fast. There are still constant factors. Here's how I do it.

Mike Dunlavey
  • 38,662
  • 12
  • 86
  • 126
0

Python:

from pprint import pprint as pp

intervals = [
    (7 , 11, 'A'),
    (1, 8, 'B'),
    (9, 12, 'C'),
    (4, 7, 'D'),
    (10, 15, 'E'),
    (0, 5, 'F'),
    (5, 9, 'H'),
    (11, 13, 'I'),
    (7, 14, 'J'),
]
intervals.sort()  # sort on interval start, then end if starts are equal
ans = []
for n0, (_, end0, name0) in enumerate(intervals[:-1]):
    for n1, (start1, _, name1) in enumerate(intervals[n0 + 1:]):
        if start1 < end0:
            ans.append(sorted((name0, name1)))
        else:
            break
pp(sorted(ans))

Output:

[['A', 'B'],
 ['A', 'C'],
 ['A', 'E'],
 ['A', 'H'],
 ['A', 'J'],
 ['B', 'D'],
 ['B', 'F'],
 ['B', 'H'],
 ['B', 'J'],
 ['C', 'E'],
 ['C', 'I'],
 ['C', 'J'],
 ['D', 'F'],
 ['D', 'H'],
 ['E', 'I'],
 ['E', 'J'],
 ['H', 'J'],
 ['I', 'J']]
Paddy3118
  • 4,262
  • 23
  • 33