Merging overlapping spans/ranges
Jim Sizelove
sizelji at insightbb.com
Tue May 10 19:53:43 EDT 2005
Bengt Richter wrote:
> On Tue, 10 May 2005 15:14:47 +0200, Max M <maxm at mxm.dk> wrote:
>
>
>>I am writing a "find-free-time" function for a calendar. There are a lot
>>of time spans with start end times, some overlapping, some not.
>>
>>To find the free time spans, I first need to convert the events into a
>>list of non overlapping time spans "meta-spans".
>>
>>This nice ascii graph should show what I mean.
>>
>>1) ---
>>2) ---
>>3) ---
>>4) -----
>>5) -----
>>
>>
>>>>------- -------- # meta spans
>>
>>I can then iterate through the meta-spans and find non-busy times.
>>
>>I have written the class below, but it is rather O^2, so I wondered if
>>anybody has an idea for a better approach?
>>
>
> Maybe (not tested beyond what you see ;-)
It is with some trepidation that I write this message; after hanging
around in c.l.p for the better part of a year, I have come to expect
Bengt's messages to be right-on and error-free.
However this time... :)
> >>> def mergespans(spans):
> ... start = end = None
> ... for s,e in sorted(spans):
> ... if start is None: start, end = s,e; continue
> ... if s <= end: end = e; continue
> ... yield start, end
> ... start,end = s,e
> ... if start is not None: yield start, end
> ...
> >>> spans = [(0,3), (4,7), (2,5), (9,14), (12,17)]
> >>> list(mergespans(spans))
> [(0, 7), (9, 17)]
There can be a problem in mergespans if one span fits inside another:
>>> spans = [(0,5), (4,7), (2,3), (9,14), (12,17)]
>>> list(mergespans(spans))
[(0, 3), (4, 7), (9, 17)]
Here is a revised version (not tested beyond what you see ;-)
>>> def mergespans(spans):
... start = end = None
... for s,e in sorted(spans):
... if start is None:
... start, end = s,e
... continue
... if s <= end:
... if end < e:
... end = e
... continue
... yield start, end
... start,end = s,e
... if start is not None:
... yield start, end
...
>>> list(mergespans([(0,5), (4,7), (2,3), (9,14), (12,17)]))
[(0, 7), (9, 17)]
>>> list(mergespans([(0,3), (4,7), (2,5), (9,14), (12,17)]))
[(0, 7), (9, 17)]
Can anyone find any other errors in this? ;-)
With humble regards,
Jim Sizelove
More information about the Python-list
mailing list