假设我有一个列表l
,其中每个元素都有一个属性time
,它存储一个浮点数,表示从某个基准点过去的秒数。每当发生某些事件时,我想从此列表中删除在此事件发生前超过T
秒发生的所有元素,因此目前我所做的是
l = [x in l if x.time > current_time - T]
这似乎是一种缓慢的做事方式。怎么能更快地完成?元素按时间排序,所以我想找到第一个不满足这个条件的元素,例如:
for i, x in enumerate(l):
if x.time > current_time - T:
break
l = l[i:]
也许有一种更好的方式?
答案 0 :(得分:0)
您可以使用deque
中的collections
。它为您提供了O(1)
复杂性,可以从列表的头部删除元素。由于元素按时间排序,而最旧的元素位于列表的开头,因此您可以轻松地逐个删除元素。
答案 1 :(得分:0)
由于它们是按时间排序的,因此您可以使用二进制搜索来查找截止点的索引,然后重新切片列表。二进制搜索应该(大致)找到截止点时的O(log n),然后是切片的O(n)。
但是,如果你经常这样做,最好使用双端队列并简单地弹出元素,直到头部“在要保持的时间内”。
所以无论什么是最好的都需要基准测试。但是,deque解决方案(可能)更容易编写,因此最好从那里开始,然后在遇到性能问题时考虑其他方法。
答案 2 :(得分:0)
import random
class Element():
def __init__(self, time):
self.time = time
l = [ Element(z*5 - random.randrange(6) + 3) for z in range( 21)]
print('list:', [z.time for z in l])
target_time = 72
print('cutoff time:', target_time)
match = False
working_list_from = 0
working_list_to = len(l)
while not match:
mid = (working_list_to - working_list_from) // 2
if l[working_list_from + mid].time < target_time:
working_list_from += mid
else:
working_list_to -= mid
match = (working_list_to - working_list_from) == 1
print(' resulting list', [z.time for z in l[working_list_from+mid:]])
结果:
list: [3, 5, 9, 18, 21, 25, 32, 33, 40, 48, 49, 57, 62, 67, 73, 73, 79, 85, 93, 94, 99]
cutoff time: 72
resulting list [73, 73, 79, 85, 93, 94, 99]