优化列表理解或替代方法

时间:2020-09-13 02:15:17

标签: python list performance

list1包含大约50,000个长度的索引列表。 list2包含一个列表或单词的长度大约为60,000。

我使用以下列表理解来遍历列表:

newList= [w for w in list2 if list2.index(w) in list1]

问题在于运行此程序需要花费相当长的时间,是否有人知道有任何提示提示或技巧来加快此过程,或者以更快的方式实现相同的结果。

我发现将list1设置为set可以加快该过程,但仍然比我想要的慢

2 个答案:

答案 0 :(得分:1)

大多数列表操作为O(n)。您的清单理解单线可能为O(n ^ 3)。因此,考虑到这一点,我建议将其分为两行,而不是一行:

indices = set(x for x in list1 if x < len(list2))
newList = [w for i,w in enumerate(list2) if i in indices]

第一行从list1中提取所有可能包含在list2中的索引。这对应于您的条款list2.index(w) in list1。第二行是选择list2中包含在索引集中的那些行。使用设置操作可以将搜索时间从O(n)减少到O(1)。使用枚举可以避免list2.index()调用,该调用还将O(n)减少为O(1)。这两行仅在O(n)时间运行。

如果您的list2包含重复项,则需要对此进行更改。但仍然可能是O(n):

indices = set(x for x in list1 if x < len(list2))
lookup = {}
for i,w in enumerate(list2):
    if w not in lookup:
        lookup[w] = i
newList = [w for w in list2 if lookup[w] in indices]

答案 1 :(得分:0)

index()需要在列表中进行搜索以找到项目的索引,并且仅找到找到的第一个项目的第一个索引(如果有重复项,则很重要)。这意味着这是O(n² )算法。然后,在整个list1中搜索它,使其成为O(n² + mn)。但是您已经知道索引了,因为您正在遍历list2 -没有理由搜索它。因此,不必再次搜索,只需将索引设置为集合,然后查看您所在的索引是否在其中。这将是O(n)。

list2 = ['hello', 'dog', 'cat', 'house']
list1 = set([0, 2, 3])

[w for i, w in enumerate(list2) if i in list1]
#['hello', 'cat', 'house']