我有一堆时间打开/关闭“规则”,我希望合并以获得当天的一套统一规则。
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)},
]
我脑子里有几种方法 - 但速度可能是选择方法的主要驱动力。
答案 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)}]