我正在使用优先级队列(heapq
)并将datetime.datetime
作为优先级。
如果我有要搜索的startTime和endTime,那么从这个列表中提取元素子集的最pythonic方法是什么。 (我不能改变原始列表,所以我必须创建一个新列表并返回,或者返回一个迭代器)
以下是我的例子:
>>> import heapq
>>> timeLine = []
>>> from datetime import datetime
>>> heapq.heappush(timeLine, (datetime.now(),'A'))
>>> heapq.heappush(timeLine, (datetime.now(),'B'))
>>> heapq.heappush(timeLine, (datetime.now(),'C'))
>>> timeLine
[(datetime.datetime(2013, 2, 8, 15, 25, 14, 720000), 'A'), (datetime.datetime(2013, 2, 8, 15, 25, 30, 575000), 'B'), (datetime.datetime(2013, 2, 8, 15, 25, 36, 959000), 'C')]
真正的应用程序列表非常庞大。
答案 0 :(得分:1)
堆不是执行此操作的理想结构;如果您坚持使用heapq
的公共API,那么堆将被更改并且无法用于进一步的操作。 @Anonymous的解决方案可能有效,但(恕我直言)过分依赖实现细节。虽然这些是公开记录的,但我不确定你是否真的应该使用它们。
简单地对列表进行排序并进行两次二进制搜索是一种简单的方法,可以按照自己的意愿进行:
from bisect import bisect_left, bisect_right
def find_range(timeline, start, end):
l = bisect_left(timeline, start)
r = bisect_right(timeline, end)
for i in xrange(l, r):
yield timeline[i]
这种方法的唯一问题是在最坏的情况下排序需要O( n lg n )时间,但是你构建堆的方式也是如此( heapq.heapify
需要线性时间。)
答案 1 :(得分:0)
堆中的每个节点都大于其所有子节点。此外,如果节点位于索引i,则其直接子节点位于索引2 * i + 1和2 * i + 2处。
将堆视为二叉树,您可以递归堆,如果条目大于您获得的maxkey(因为它的所有子项将更大),则停止,并且如果其键位于其间,则输出该节点minkey和maxkey。
把它放在一起就可以了:
def extract_range(h, i, minkey, maxkey):
if i >= len(h) or h[i][0] >= maxkey:
return
if h[i][0] >= minkey:
yield h[i]
for k in 1, 2:
for r in extract_range(h, 2 * i + k, minkey, maxkey):
yield r