找到多组交集的最佳方法是什么?

时间:2010-03-29 22:44:19

标签: python set set-intersection

我有一个集合列表:

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

我想要s1∩s2∩s3...

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

是否有推荐的,更好的或内置的方式?

7 个答案:

答案 0 :(得分:373)

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

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

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

u = set.intersection(*setlist)

其中*a_listlist expansion

答案 1 :(得分:61)

从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])

答案 2 :(得分:17)

显然set.intersection就是你想要的,但是如果你需要概括为“把所有这些的总和”,“取所有这些的产物”,“把所有这些的xor” ,你要找的是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}

答案 3 :(得分:11)

如果你没有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程序员不喜欢它,including Guido himself

  

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

     

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

答案 4 :(得分: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,但我很喜欢它:)

答案 5 :(得分:1)

让-弗朗索瓦·法布尔(Jean-FrançoisFabre)set.intesection(* list_of_sets)答案无疑是最pyhtonic的答案,也是正确的答案。

对于那些希望使用reduce的用户,以下操作也将起作用:

reduce(set.intersection, list_of_sets)

答案 6 :(得分: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])