Merging overlapping spans/ranges

Mike Rovner mrovner at propel.com
Tue May 10 16:38:54 EDT 2005


Max M 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".
> 

"Almost" linear method (includes .sort() which is afaik N*logN):
[Set all priority to 1, or you will get changes in priorities as well.]

def merge(p):
     """ p is a seq of (start, priority, end)
     returns list of merged events:
       (start1, pri), (end1, 0), (start2, pri), (end2, 0), ...
     """
     all=[] # list of x, h, up, id
     for id,(l,h,r) in enumerate(p):
         all.append((l,h,1,id))
         all.append((r,h,0,id))
     all.sort()

     sl = [] # skyline solution
     slx = slh = 0 # current values
     vis = {} # active {id:h}
     for x,h,up,id in all:
         if up:
             vis[id]=h
             if h>slh:
                 sl.append((x,h))
                 slh=h
         else:
             del vis[id]
             assert h<=slh
             if h==slh:
                 v = vis.values()
                 if v:
                     h = max(v)
                 else:
                     h = 0
                 sl.append((x,h))
                 slh=h
         slx=x
     # merge same time events
     s=dict(sl)
     sl=s.keys()
     sl.sort()
     return [(k,s[k]) for k in sl]




More information about the Python-list mailing list