Python - 找到最接近的时间戳

时间:2011-11-17 05:05:16

标签: python algorithm search timestamp

我有一个Python日期时间戳和一个大的dict(索引),其中键是时间戳,值是我感兴趣的其他一些信息。

我需要尽可能有效地在索引中找到最接近时间戳的日期时间(键)。

目前我正在做类似的事情:

for timestamp in timestamps:
    closestTimestamp = min(index,key=lambda datetime : abs(timestamp - datetime))

哪个有效,但需要太长时间 - 我的索引字典有数百万个值,我正在进行数千次搜索。我对数据结构很灵活等等 - 时间戳大致是顺序的,所以我从第一个时间戳到最后一个时间戳进行迭代。同样,我加载到dict中的文本文件中的时间戳是顺序的。

非常感谢任何优化建议。

3 个答案:

答案 0 :(得分:23)

字典不是为有效的近距离搜索而组织的。它们专为完全匹配而设计(使用hash table)。

你可能会更好地保持一个单独的,可快速搜索的有序结构。

一种简单的启动方式是使用bisect module进行快速O(log N)搜索,但使用较慢的O(n)插入:

def nearest(ts):
    # Given a presorted list of timestamps:  s = sorted(index)
    i = bisect_left(s, ts)
    return min(s[max(0, i-1): i+2], key=lambda t: abs(ts - t))

适用于非静态,动态更新的dicts的更复杂的方法是使用blist,它采用树结构进行快速O(log N)插入和查找。如果dict会随着时间的推移而改变,你只需要这个。

如果您希望继续使用基于字典的方法,请考虑使用附近时间戳对条目进行聚类的列表词典:

 def get_closest_stamp(ts):
      'Speed-up timestamp search by looking only at entries in the same hour'
      hour = round_to_nearest_hour(ts)
      cluster = daydict[hour]         # return a list of entries
      return min(cluster, key=lambda t: abs(ts - t))

注意,对于群集边界附近的精确结果,请在主群集和相邻群集中存储接近边界的时间戳。

答案 1 :(得分:3)

datetime对象彼此相似,因此请按如下所示制作键/值对的排序列表:

myPairs = list(dict.iteritems())
myPairs.sort()

对于每个元素myPairs[i]myPairs[i][0]datetime键,myPairs[i][1]是值。

您可以使用bisect_left高效搜索此列表:

import bisect
i = bisect.bisect_left(myPairs, targetDatetime)

元素myPairs[i]是日期时间最短不早于targetDatetime的元素。但是先前的元素(如果有的话)可能会更接近targetDatetime。或targetDatetime可能比myPairs中的任何时间晚。所以你需要检查:

if i > 0 and i == len(myPairs):
    i -= 1
elif i > 0 and targetDatetime - myPairs[i-1][0] < myPairs[i][0]- targetDatetime:
    i -= 1

答案 2 :(得分:2)

如果您的列表是真正排序的,而不仅仅是“大致顺序”,您可以使用二进制搜索。有关详细信息,请查看bisect module documentation