Python 列表交集效率:生成器还是 filter()?

16 投票
4 回答
17126 浏览
提问于 2025-04-16 19:41

我想在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)

还有其他建议吗?

提前谢谢你,
Amnon

4 个回答

7

我试着比较了三种列表交集的方法的速度:

import random

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

方法一:列表推导

耗时: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) 

方法二:集合

耗时:0.09089064598083496

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

方法三:numpy.intersect1d

耗时:0.323300838470459

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

结论

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

8

你的解决方案的复杂度是 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%。

32

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

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

集合是可以遍历的,所以不需要把结果转换成其他形式。

撰写回答