python中的“合并”时间范围

时间:2017-10-17 07:14:55

标签: python datetime

我有一堆时间打开/关闭“规则”,我希望合并以获得当天的一套统一规则。

from datetime import time

times = [
    {"time_open": time(9, 0), "time_close": time(11, 0)},
    {"time_open": time(9, 0), "time_close": time(12, 0)},
    {"time_open": time(13, 0), "time_close": time(18, 0)},
    {"time_open": time(15, 0), "time_close": time(19, 0)},
]

# something would produce

merged_times = [
    {"time_open": time(9, 0), "time_close": time(12, 0)},
    {"time_open": time(13, 0), "time_close": time(19, 0)},
]

我脑子里有几种方法 - 但速度可能是选择方法的主要驱动力。

1 个答案:

答案 0 :(得分:3)

您需要从一组有序的间隔开始;如果他们还没有排序,那就开始了:

from operator import itemgetter

sorted_times = sorted(times, key=itemgetter('time_open', 'time_close'))

然后,您可以简单地通过比较开始时间和前一个结束时间来合并时间;当他们没有超过产生更新的时间时:

def merge_times(times):
    times = iter(times)
    merged = next(times).copy()
    for entry in times:
        start, end = entry['time_open'], entry['time_close']
        if start <= merged['time_close']:
            # overlapping, merge
            merged['time_close'] = max(merged['time_close'], end)
        else:
            # distinct; yield merged and start a new copy
            yield merged
            merged = entry.copy()
    yield merged

这是一个生成器函数,因此可以按需生成合并时间。使用循环逐个处理这些,或者使用生成器上的list()将所有结果拉入列表对象。

使用您的样本数据进行演示(恰好已经排序):

>>> for entry in merge_times(times):
...     print(entry)
...
{'time_open': datetime.time(9, 0), 'time_close': datetime.time(12, 0)}
{'time_open': datetime.time(13, 0), 'time_close': datetime.time(19, 0)}
>>> list(merge_times(times))
[{'time_open': datetime.time(9, 0), 'time_close': datetime.time(12, 0)}, {'time_open': datetime.time(13, 0), 'time_close': datetime.time(19, 0)}]