我有一些(非常大的)元组列表来自包含id,start_time和end_time的数据库
我还有一个定期间隔的时间列表并且有序(这些都是日期时间对象)。
我基本上需要遍历这些时间并找到时间落在其范围内的所有元组。
我想知道最有效的方法是什么。想到的第一个想法是这样的(伪代码):
for time in times:
for tuple in tuples:
if tuple.start_time <= time <= tuple.end_time:
# add tuple to some_other_list
if tuple.end_time < time
# remove tuple from tuples
我这样做的原因是迭代越来越小的列表,希望在那里缩短一些时间,但我也对完全不同的方法持开放态度。我想另一个想法是在每次迭代时用给定时间查询数据库,但我想象那里的延迟远远超过在内存中使用完整数据集并以这种方式使用它。
例如,我会得到一个元组列表,其中每个元组都是这样的:
[('783', datetime.datetime(2017, 12, 31, 20, 49, 28), datetime.datetime(2017, 12, 31, 23, 49, 28)), ('5274', datetime.datetime(2017, 12, 31, 20, 49, 45), datetime.datetime(2018, 1, 1, 0, 0)), ('757', datetime.datetime(2017, 12, 31, 20, 50, 25), datetime.datetime(2018, 1, 1, 1, 50, 25)), ('5600', datetime.datetime(2017, 12, 31, 20, 50, 59), datetime.datetime(2017, 12, 31, 23, 39)), ('5176', datetime.datetime(2017, 12, 31, 20, 51, 23), datetime.datetime(2018, 1, 1, 1, 51, 23)), ('5323', datetime.datetime(2017, 12, 31, 20, 52, 39), datetime.datetime(2018, 1, 1, 0, 0)), ('464', datetime.datetime(2017, 12, 31, 20, 52, 41), datetime.datetime(2018, 1, 1, 0, 52, 41))]
并且时间列表将存储在生成器basically using this answer中,因此循环遍历它们会产生如下内容:
2017-12-15 00:00:00
2017-12-22 00:00:00
2017-12-29 00:00:00
2018-01-05 00:00:00
2018-01-12 00:00:00
2018-01-19 00:00:00
实际输出我是不可知的,它只是一些字典
{'2017-12-15 00:00:00': [list of matching ids], '2017-12-22 00:00:00': [list of matching ids], ...}
任何想法或建议都将不胜感激!
答案 0 :(得分:1)
首先,关于删除不相关间隔的注意事项:如果从(长)列表中执行此操作,则性能将非常糟糕,因为需要将后续元素移动到空白区域。可以通过使用一个整数替换已删除的元素来解决这个问题,该整数表示跳过多远可以找到下一个真实数据。
这是典型的区间查询问题,通常的答案是interval或segment树。但是,如果您可以同时存储所有结果(以及所有已排序的查询时间),则可以使用一个简单的替代方法:而不是迭代时间然后搜索间隔,迭代一次间隔并执行二进制搜索以查找每个间隔包含的最早和最晚查询时间。然后将间隔的ID附加到为每个这样的时间维护的列表中:
def ids(iv,tm):
ret=[[] for _ in tm]
for nm,l,h in iv:
for i in range(bisect.bisect_left(tm,l),bisect.bisect_right(tm,h)):
ret[i].append(nm)
return ret
您当然可以使用dict(zip(tm,ids(iv,tm)))
从结果中构建字典。