提高列表删除的时间效率

时间:2018-04-22 08:21:19

标签: python performance list dictionary

更快捷的方式是什么?删除"我已经附加到我的序列中的项目,所以我不会再次遇到它们?在我的实际代码中,我有更大的单词序列,因此使用.remove(word)的时间非常昂贵。

我目前的想法:

  • 将单词存储在heapq而不是列表中,并按照我正在使用的启发式对它们进行排序。 (这里的问题是我需要在从序列中删除一个单词后更新启发式值,因此我不相信它有助于时间复杂度)

  • 使用哈希映射来检查单词是否在序列中。在这种情况下,时间复杂度如何?

我有以下代码(为了简单起见,我使用random.choice,因为我实际上使用启发式来选择下一个单词):

import random
d = {'b': ['bob', 'bun', 'bom'], 'd': ['dob', 'don'], 'm': ['mox']}

print(d)
seq = []
current = 'bob'
seq.append(current)
d[current[:1]].remove(current)
while current[-1:] in d and d[current[-1:]]:
    next_ = random.choice(d[current[-1:]])
    current = next_
    seq.append(current)
    d[current[:1]].remove(current)

print(d)
print(seq)

示例输出:

{'b': ['bob', 'bun', 'bom'], 'd': ['dob', 'don'], 'm': ['mox']}
{'b': ['bun'], 'd': ['dob', 'don'], 'm': []}
['bob', 'bom', 'mox']

1 个答案:

答案 0 :(得分:1)

如果您希望保持列表不变,但是项目的顺序无关紧要,则需要以下内容。如果您不需要将列表与其所有项目保持一致,则可以更轻松地将项目与最后一项L[-1], L[idx] = L[idx], L[-1]交换,然后拨打L.pop()

实际上不要删除任何东西。保留每个列表的计数,并将该元素与要删除的元素交换并减少计数:

所以[0, []]是空列表,[3, [1,2,3]]是删除1之前的列表,而[2, [3,2,1]]是之后的列表。

这使得删除项目与Knuth shuffle步骤有效。然后选择一个随机项,您将生成一个介于0和剩余计数之间的数字,然后将该索引与剩余计数减去1的项交换。

生成一个:[len(L)+1, L]

选择一个随机项目:

remaining_count, L = cL
idx = random.randrange(0, remaining_count)
value = L[idx]
L[remaining_count - 1], L[idx] = L[idx], L[remaining_count - 1]
cL[0] = remaining_count - 1
当列表耗尽时,

random.randrange会在remaining_count-1时引发ValueError。

结果是在O(1)时间内删除了项目。您可以将列表恢复为原始项目,但也可以通过{(1)}在O(1)中以随机顺序恢复。

如果您需要修剪已删除的元素,可以使用单个方法完成:

cL[0] = len(cL[1])

在remaining_count减1之后删除元素,并且此操作发生在列表的末尾,其成本很低。