根据滚动队列的时间戳从defalutdict(列表)中删除项目

时间:2015-03-29 20:50:06

标签: python

我正在跟踪csv文件中的大量对象,并试图找出在滚动的5分钟间隔内发生了多少事件(对于每组玩家)。我正在使用defaultdict存储事件时间,然后计算存储的事件数量,以便为我提供滚动总数。每次从csv调用一行时,它应该检查该播放器的defaultdict中的时间戳,如果任何时间超过5分钟(300秒),则将它们从defaultdict中删除。它似乎有点工作,但它永远不会一直下​​降到0(当玩家的任何事件之间超过5分钟时)。希望有人能告诉我这里我做错了什么:

fishrollingmeanqueue = defaultdict(list)
def fishInLastNSeconds(num_seconds,ts,player): #I set num_seconds to 300 elsewhere, ts = timestamp for the event
    curTime = timestampToEpoch(ts)
    fishrollingmeanqueue[player].append(curTime)
    for elt in fishrollingmeanqueue[player]:
        if elt < (curTime - num_seconds):
            fishrollingmeanqueue[player].remove(elt)
    return str(len(fishrollingmeanqueue[player])) 

1 个答案:

答案 0 :(得分:1)

您遇到的问题是由于您在迭代列表的同时修改了列表。这不正常,因为列表迭代器按索引进行,后一项的索引将在删除之前的项时更改。

例如,考虑一个三元素列表lst=[a,b,c]。当您使用for elt in lst迭代它时,Python将创建一个迭代器,它最初位于索引0。在第一次循环中,elt将引用a,即该索引处的对象。如果在循环内删除a lst.remove(elt),则列表现在为[b,c]。在下一个传递中,迭代器将指向索引1,您将c作为elt。原始列表的第二个元素b将被跳过。

有几种方法可以解决这个问题。通常最好的方法是创建一个只包含您要保留的项目的新列表,然后用新的列表替换旧列表:

new_q = [elt for elt in fishrollingmeanqueue[player] if elt >= curTime - num_seconds]
fishrollingmeanqueue[player] = newq

其他选项是迭代列表的副本,或反向迭代,以便尚未看到的值的索引不会改变。