Python - 多个列表的交集?

95

我正在使用Python进行编程,可以获取两个列表的交集:

result = set(a).intersection(b)

现在假设 d 是一个列表,其中包含 ab 这两个元素以及第三个元素 c,那么是否有内置函数可以找到 d 中所有三个列表的交集?举例来说,

d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]

那么结果应该是

[3,4]
6个回答

125
set.intersection(*map(set,d))

1
不确定这里出了什么问题。现在它给我:TypeError: intersection() takes exactly one argument (2 given) - Legend
1
非常感谢。+1。我只是因为我的Python版本无法使用它而感到困扰:( - Legend
3
如果变量 d 的长度可能为零,则 set.intersection 函数将引发 TypeError 异常。我建议捕获该异常并在这种退化情况下返回 set()(一个空集)而不是事先检查 d 的长度,因为它可能是一个生成器。 - Aaron Robson
@TokenMacGuy:是的,你说得很对;类比于http://en.wikipedia.org/wiki/Empty_product,它将是唯一保证不改变交集结果的集合。 - Aaron Robson
@CesareIurlaro 这是一个内置函数... 文档链接 => 内置类型 — Python 3.9.6 文档 - user202729
显示剩余2条评论

65

对于版本为2.4,您可以定义一个intersection函数。

def intersect(*d):
    sets = iter(map(set, d))
    result = sets.next()
    for s in sets:
        result = result.intersection(s)
    return result

对于较新版本的Python:

intersection方法可以接受任意数量的参数。

result = set(d[0]).intersection(*d[1:])

另一种方法是将第一个集合与其自身相交,以避免切片列表并进行复制:

result = set(d[0]).intersection(*d)

我不确定哪种方法更有效率,但感觉这将取决于 d [0] 的大小以及列表的大小,除非Python内置有针对此的检查。

if s1 is s2:
    return s1
在交集方法中。
>>> d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]
>>> set(d[0]).intersection(*d)
set([3, 4])
>>> set(d[0]).intersection(*d[1:])
set([3, 4])
>>> 

@Legend。你必须先将它映射到一个集合上。我不知道它们是列表。之后,你可以将列表(或任何其他可迭代对象)传递给intersection方法。 - aaronasterling
@AaronMcSmooth:其实,我不确定为什么,但无论我尝试什么解决方案,都会出现这个错误:TypeError: intersection() takes exactly one argument (3 given) - Legend
@AaronMcSmooth:啊...有没有Python 2.4的解决方案呢? - Legend
16
@Legend 谢谢你修改我的帖子。但是请记住:“主如此说:‘你应该用四个空格缩进,不多不少。你的缩进数量应为四个,而你的缩进次数也应为四次。你不应该缩进八次,也不应该缩进两次,除非你接着再缩进四次。制表符是魔鬼的苹果!’” - aaronasterling
我相信你打错了: result = set(d[0]).intersection(*d[:1]) 应该是: result = set(d[0]).intersection(*d[1:])。否则你只会得到第一个列表。 - Alex
显示剩余6条评论

13

@user3917838

这段代码简单易懂,但是需要一些强制类型转换来使它能够工作并给出一个列表作为结果。代码应该像这样:

list(reduce(set.intersection, [set(item) for item in d ]))

其中:

d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]

结果是:

[3, 4]

至少在Python 3.4版本中


13

您可以使用set.intersection(set1, set2, set3...)获得任意数量集合的交集。因此,您只需要将列表转换为集合,然后按以下方式将它们传递给该方法:

d = [[1,2,3,4], [2,3,4], [3,4,5,6,7]]  
set.intersection(*[set(x) for x in d])  

结果:

{3, 4}

4

我认为reduce()特别有用。事实上,numpy文档建议使用reduce()来求多个列表的交集:numpy.intersect1d reference

回答你的问题:

import numpy as np
from functools import reduce
# apply intersect1d to (a list of) multiple lists:
reduce(np.intersect1d, [list_1, list_2, ... list_n])

4

Lambda reduce.

from functools import reduce #you won't need this in Python 2
l=[[1, 2, 3, 4], [2, 3, 4], [3, 4, 5, 6, 7]]
reduce(set.intersection, [set(l_) for l_ in l])

3
您需要一个集合列表,但是会出现“描述符交集需要集合”的错误。 - tj89

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接