Python 从时间顺序列表中删除旧元素

Python 从时间顺序列表中删除旧元素,python,performance,list,Python,Performance,List,假设我有一个列表l,其中每个元素都有一个属性time,该属性存储一个浮点数,表示从某个基准点经过的秒数。每当某个事件发生时,我想从列表中删除在此事件发生前超过T秒的所有元素,因此当前我要做的是 l = [x in l if x.time > current_time - T] 这似乎是一种缓慢的做事方式。如何才能更快地做到这一点?元素在这里是按时间排序的,所以我想找到第一个不满足这个条件的元素,例如 for i, x in enumerate(l): if x.time >

假设我有一个列表
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:]

也许有更好的方法?

您可以使用
集合中的
deque
。它为您提供了从列表头部删除元素的复杂性。由于元素是按时间排序的,并且最早的元素位于列表的顶部,因此可以轻松地逐个删除元素。

您可以使用
集合中的
deque
。它为您提供了从列表头部删除元素的复杂性。由于元素是按时间排序的,并且最早的元素位于列表的顶部,因此可以轻松地逐个删除元素。

由于元素是按时间排序的,因此可以使用二进制搜索来查找截止点的索引,然后重新对列表进行切片。在寻找截止点时,二进制搜索应该(大致)为O(logn),然后在切片时为O(n)

但是,如果您经常这样做,那么最好使用deque并简单地弹出元素,直到头部“在保留期内”


因此,无论什么是最好的,都需要进行基准测试。然而,DEQE解决方案可能更容易编写,所以最好是从那里开始,然后考虑其他方法,如果你看到性能问题。

< P>因为它们是按时间顺序排列的,可以使用二进制搜索找到截止点的索引,然后重新切片列表。在寻找截止点时,二进制搜索应该(大致)为O(logn),然后在切片时为O(n)

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:]])
但是,如果您经常这样做,那么最好使用deque并简单地弹出元素,直到头部“在保留期内”

因此,无论什么是最好的,都需要进行基准测试。但是,DeQE解决方案可能更容易编写,所以最好是从那里开始,然后考虑其他方法,如果你看到性能问题。
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:]])