从python的另一个列表中排除列表元素的最快方法是什么?

时间:2013-11-15 19:54:41

标签: python

我有大量的2个列表,我希望将彼此的元素排除在外。

做普通

会更快吗?
[x for x in list1 if x not in list2] 

或者我应该以另一种格式(setdictionary使用键类型=无,hashMap)转换list1和/或list2,还是使用一些预先实现的包函数? 感谢。

修改 订单无关紧要。

6 个答案:

答案 0 :(得分:4)

这是你的慢速方法:

[x for x in list1 if x not in list2] #O(n*m)

这是一个EVEN SLOWER方法:

[x for x in list1 if x not in set(list2)] #O(n*m) with extra overhead

这是一种快速方法:

s = set(list2) #O(m)
[x for x in list1 if x not in s] #O(n)

x in list2是O(n)操作。 set(list2)中的x对于in部分是O(1),而对于集合构建部分是O(n)。第二种方法更慢的原因是它为每个成员资格测试构建了一个新的set,而不是只构建一次并对其进行查找。

答案 1 :(得分:1)

其他人已经打败了我的Python内存解决方案,但我想补充说,这似乎是治疗症状而不是治愈疾病的情况。为什么首先列出内存大的列表?

显然我不知道应用程序的性质,但考虑使用数据库,运行后台批处理作业和缓存结果等替代方案,尝试用更好的设计解决这个问题。

答案 2 :(得分:1)

如果您可以使用套装,则不会重复项目:

a = set(list1)
b = set(list2)

c = a.difference(b)

答案 3 :(得分:1)

我会选择设置解决方案,控制台中的快速微基准可能看起来像这样(我个人不会担心设置构造开销,除非经常执行):

list1 = range(50000)
list2 = range(10000, 20000)

%timeit [x for x in list1 if x not in list2]
# 8.48 s per loop


slist2 = set(list2)

%timeit [x for x in list1 if x not in slist2]
# 3.62 ms per loop

答案 4 :(得分:1)

这是一种破坏原始订单的方法,但可能更快,“取决于”。它依赖于elements()对象鲜为人知的collections.Counter方法:

from collections import Counter

xs = ["abc", "def", "abc", "abc", "def", "def", "xyz"]
ys = ["def", "def", "jik"]

xsc = Counter(xs)
for y in set(ys):  # if y has few repeated elements, skip `set()`
    xsc[y] = 0
print list(xsc.elements())

打印(可能 - 订单未定义!):

['xyz', 'abc', 'abc', 'abc']

答案 5 :(得分:0)

加速的唯一方法是对list2中的成员资格进行测试,因此请尝试

[ x for x in list1 if x not in set(list2) ]

这是否更快取决于对集合执行len(list1)操作所节省的时间是否弥补了构建集合所需的时间,这取决于两个列表的长度。