343

我有一个集合列表:

setlist = [s1,s2,s3...]

我想要 s1 ∩ s2 ∩ s3 ...

我可以通过执行一系列 pairwises1.intersection(s2)等来编写一个函数来完成它。

有推荐的、更好的或内置的方式吗?

4

7 回答 7

554

从 Python 2.6 版开始,您可以使用多个参数set.intersection(),例如

u = set.intersection(s1, s2, s3)

如果集合在列表中,则转换为:

u = set.intersection(*setlist)

*a_list列表扩展在哪里

请注意,这不是set.intersection静态方法,但它使用函数符号来应用第一个集合与列表其余部分的交集。因此,如果参数列表为空,这将失败。

于 2010-03-29T22:55:34.360 回答
86

从 2.6 开始,set.intersection可以任意多次迭代。

>>> s1 = set([1, 2, 3])
>>> s2 = set([2, 3, 4])
>>> s3 = set([2, 4, 6])
>>> s1 & s2 & s3
set([2])
>>> s1.intersection(s2, s3)
set([2])
>>> sets = [s1, s2, s3]
>>> set.intersection(*sets)
set([2])
于 2010-03-29T22:58:49.693 回答
27

显然set.intersection是你想要的,但如果你需要“取所有这些的总和”、“取所有这些的乘积”、“取所有这些的异或”的概括,你正在寻找的是reduce功能:

from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}

或者

print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
于 2012-02-29T01:18:36.020 回答
12

如果您没有 Python 2.6 或更高版本,另一种方法是编写显式 for 循环:

def set_list_intersection(set_list):
  if not set_list:
    return set()
  result = set_list[0]
  for s in set_list[1:]:
    result &= s
  return result

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print set_list_intersection(set_list)
# Output: set([1])

您还可以使用reduce

set_list = [set([1, 2]), set([1, 3]), set([1, 4])]
print reduce(lambda s1, s2: s1 & s2, set_list)
# Output: set([1])

然而,许多 Python 程序员不喜欢它,包括 Guido 自己

大约 12 年前,Python 获得了 lambda、reduce()、filter() 和 map(),感谢(我相信)一个错过了这些并提交了工作补丁的 Lisp 黑客。但是,尽管有 PR 值,我认为这些功能应该从 Python 3000 中删除。

所以现在减少()。这实际上是我一直最讨厌的一个,因为除了一些涉及 + 或 * 的示例之外,几乎每次我看到带有非平凡函数参数的 reduce() 调用时,我都需要拿起笔和纸来在我理解 reduce() 应该做什么之前,先画出实际输入该函数的内容。所以在我看来,reduce() 的适用性几乎仅限于关联运算符,在所有其他情况下,最好明确地写出累积循环。

于 2010-03-29T22:53:30.713 回答
1

在这里,我为多个集合交集提供了一个通用函数,试图利用可用的最佳方法:

def multiple_set_intersection(*sets):
    """Return multiple set intersection."""
    try:
        return set.intersection(*sets)
    except TypeError: # this is Python < 2.6 or no arguments
        pass

    try: a_set= sets[0]
    except IndexError: # no arguments
        return set() # return empty set

    return reduce(a_set.intersection, sets[1:])

Guido 可能不喜欢reduce,但我有点喜欢它 :)

于 2010-03-31T22:50:38.383 回答
1

Jean-François Fabre set.intesection(*list_of_sets) 答案绝对是最 Pyhtonic 并且正确地被接受的答案。

对于那些想要使用 reduce 的人,以下内容也可以使用:

reduce(set.intersection, list_of_sets)

于 2020-05-01T11:50:27.003 回答
0

我相信最简单的做法是:

#assuming three sets
set1 = {1,2,3,4,5}
set2 = {2,3,8,9}
set3 = {2,10,11,12}

#intersection
set4 = set1 & set2 & set3

set4 将是 set1 、 set2 、 set3 的交集,并将包含值 2。

print(set4)

set([2])
于 2020-11-13T15:17:00.690 回答