Python列表交集效率:generator还是filter()?

时间:2011-06-16 09:13:56

标签: python list intersection python-2.7 intersect

我想在Python(2.7)中交叉两个列表。我需要结果可迭代:

list1 = [1,2,3,4]
list2 = [3,4,5,6]
result = (3,4) # any kind of iterable

提供完整迭代将在交叉点后首先执行,以下哪项更有效?

使用发电机:

result = (x for x in list1 if x in list2)

使用filter():

result = filter(lambda x: x in list2, list1)

其他建议?

提前致谢,
暗嫩

4 个答案:

答案 0 :(得分:17)

这些都不是。最好的方法是使用集合。

list1 = [1,2,3,4]
list2 = [3,4,5,6]
result = set(list1).intersection(list2)

集合是可迭代的,因此无需将结果转换为任何内容。

答案 1 :(得分:7)

您的解决方案的复杂度为O(m*n),其中mn是两个列表的相应长度。您可以使用其中一个列表的集合来提高O(m+n)的复杂性:

s = set(list1)
result = [x for x in list2 if x in s]

如果速度比可读性更重要(即几乎从不),您也可以使用

result = filter(set(a).__contains__, b)

比我机器上的其他解决方案快20%左右。

答案 2 :(得分:1)

对于列表的情况,最有效的方法是使用:

result = set(list1).intersection(list2)

如上所述,但对于numpy数组,intersection1d函数效率更高:

import numpy as np
result = np.intersection1d(list1, list2)

特别是,当您知道列表没有重复值时,您可以将其用作:

result = np.intersection1d(list1, list2, assume_unique=True)

答案 3 :(得分:0)

我试图比较3种列表交集方法的速度:

import random

a = [random.randint(0, 1000) for _ in range(1000)]
b = [random.randint(0, 1000) for _ in range(1000)]

解决方案1:列表理解

经过时间: 8.95265507698059

import time
start = time.time()
for _ in range(1000):
    result = [x for x in a if x in b]
elapse = time.time() - start
print(elapse) 

解决方案2:设置

经过时间: 0.09089064598083496

start = time.time()
for _ in range(1000):
    result = set.intersection(set(a), set(b))
elapse = time.time() - start
print(elapse) 

解决方案3:numpy.intersect1d

经过的时间: 0.323300838470459

start = time.time()
for _ in range(1000):
    result = np.intersect1d(a, b)
elapse = time.time() - start
print(elapse) 

结论

我认为使用set.intersection是最快的方法。