2015-02-12 137 views
1

我和日期列表:Python的比较日期范围列表

dates = [ 
    {'start': 2015-02-12 08:30, 'end': 2015-02-12 13:30, 'name': 'a'}, 
    {'start': 2015-02-12 09:00, 'end': 2015-02-12 11:45, 'name': 'b'}, 
    {'start': 2015-02-12 09:30, 'end': 2015-02-12 10:30, 'name': 'c'}, 
    {'start': 2015-02-12 10:30, 'end': 2015-02-12 17:30, 'name': 'd'}, 
    {'start': 2015-02-12 11:00, 'end': 2015-02-12 20:30, 'name': 'e'}, 
    {'start': 2015-02-12 12:30, 'end': 2015-02-12 18:30, 'name': 'f'}, 
] 

,我需要得到输出(合并这些日期的时间间隔)是这样的:

output = [ 
    {'start': 2015-02-12 08:30, 'end': 2015-02-12 09:00, 'name': 'a'}, 
    {'start': 2015-02-12 09:00, 'end': 2015-02-12 09:30, 'name': 'a + b'}, 
    {'start': 2015-02-12 09:30, 'end': 2015-02-12 10:30, 'name': 'a + b + c'}, 
    {'start': 2015-02-12 10:30, 'end': 2015-02-12 11:00, 'name': 'a + b + d'}, 
    {'start': 2015-02-12 11:00, 'end': 2015-02-12 11:45, 'name': 'a + b + d + e'}, 
    {'start': 2015-02-12 11:45, 'end': 2015-02-12 12:30, 'name': 'a + d + e'}, 
    {'start': 2015-02-12 12:30, 'end': 2015-02-12 13:30, 'name': 'a + d + e + f'}, 
    {'start': 2015-02-12 13:30, 'end': 2015-02-12 17:30, 'name': 'd + e + f '}, 
    {'start': 2015-02-12 17:30, 'end': 2015-02-12 18:30, 'name': 'e + f'}, 
    {'start': 2015-02-12 18:30, 'end': 2015-02-12 20:30, 'name': 'f'}, 
] 

每个输出startend日期必须按顺序,如果一个项目startend日期彼此交叉,他们应该合并。

我试图在环

for x, left in enumerate(dates): 
    for y, right in enumerate(dates): 
     # HERE GOES THE LOGIC.. 
     # Tried to compare each X and Y item with each other 
     # But don't know how to keep used items "in mind" 
     # And then create new list to output 
     continue 

使用循环,但没有找到一个解决方案来解决这个问题。 我在等待帮助解答,谢谢。

回答

1

尝试这样的:

date_ranges = [ 
    {'start': '2015-02-12 08:30', 'end': '2015-02-12 13:30', 'name': 'a'}, 
    # Omitting... 
    {'start': '2015-02-12 12:30', 'end': '2015-02-12 18:30', 'name': 'f'}, 
] 

edges = set() 
for date_range in date_ranges: 
    edges.add(date_range['start']) 
    edges.add(date_range['end']) 
edges = sorted(list(edges)) 

intervals = [] 
for i, edge in enumerate(edges): 
    if i == 0: 
     continue 
    previous_edge = edges[i - 1] 
    current_edge = edge 
    overlaps = [date_range['name'] 
       for date_range in date_ranges 
       if date_range['start'] <= previous_edge and 
        current_edge <= date_range['end']] 
    if overlaps: 
     interval = { 
      'name': ' + '.join(sorted(overlaps)), 
      'start': previous_edge, 
      'end': current_edge 
     } 
     intervals.append(interval) 

for interval in intervals: 
    print interval 

输出:

{'start': '2015-02-12 08:30', 'end': '2015-02-12 09:00', 'name': 'a'} 
{'start': '2015-02-12 09:00', 'end': '2015-02-12 09:30', 'name': 'a + b'} 
{'start': '2015-02-12 09:30', 'end': '2015-02-12 10:30', 'name': 'a + b + c'} 
{'start': '2015-02-12 10:30', 'end': '2015-02-12 11:00', 'name': 'a + b + d'} 
{'start': '2015-02-12 11:00', 'end': '2015-02-12 11:45', 'name': 'a + b + d + e'} 
{'start': '2015-02-12 11:45', 'end': '2015-02-12 12:30', 'name': 'a + d + e'} 
{'start': '2015-02-12 12:30', 'end': '2015-02-12 13:30', 'name': 'a + d + e + f'} 
{'start': '2015-02-12 13:30', 'end': '2015-02-12 17:30', 'name': 'd + e + f'} 
{'start': '2015-02-12 17:30', 'end': '2015-02-12 18:30', 'name': 'e + f'} 
{'start': '2015-02-12 18:30', 'end': '2015-02-12 20:30', 'name': 'e'} 
1
# To keep the example simple, I'm using floats instead of times. 
dates = [ 
    {'start': 8.30, 'end': 13.30, 'name': 'a'}, 
    {'start': 9.00, 'end': 11.45, 'name': 'b'}, 
    {'start': 9.30, 'end': 10.30, 'name': 'c'}, 
    {'start': 10.30, 'end': 17.30, 'name': 'd'}, 
    {'start': 11.00, 'end': 20.30, 'name': 'e'}, 
    {'start': 12.30, 'end': 18.30, 'name': 'f'}, 
                # A gap. 
    {'start': 22.00, 'end': 22.30, 'name': 'g'}, 
] 

# Get list of all times, with a boolean to mark their type. 
times = [] 
for d in dates: 
    times.append((d['start'], False, d['name'])) 
    times.append((d['end'], True, d['name'])) 

# Process them in sorted order. 
active = set() 
for t, is_end, name in sorted(times): 
    if active and t != prev: 
     print (prev, t), '+'.join(active) 
    prev = t 
    if is_end: active.remove(name) 
    else:  active.add(name) 

输出:

(8.3, 9.0) a 
(9.0, 9.3) a+b 
(9.3, 10.3) a+c+b 
(10.3, 11.0) a+b+d 
(11.0, 11.45) a+b+e+d 
(11.45, 12.3) a+e+d 
(12.3, 13.3) a+e+d+f 
(13.3, 17.3) e+d+f 
(17.3, 18.3) e+f 
(18.3, 20.3) e 
(22.0, 22.3) g 
+0

感谢@FMc的答案,这是真的很有帮助。 – gordon33 2015-02-12 09:23:24