Python 找到多个集合交集的最佳方法?
我有一个集合列表:Python 找到多个集合交集的最佳方法?,python,set,set-intersection,Python,Set,Set Intersection,我有一个集合列表: setlist = [s1,s2,s3...] 我要s1∩ s2∩ s3 我可以编写一个函数,通过执行一系列成对的s1.交集(s2)等来实现 有推荐的、更好的或内置的方法吗?如果您没有Python 2.6或更高版本,另一种方法是编写一个显式for循环: def set_list_intersection(set_list): if not set_list: return set() result = set_list[0] for s in set_l
setlist = [s1,s2,s3...]
我要s1∩ s2∩ s3
我可以编写一个函数,通过执行一系列成对的s1.交集(s2)
等来实现
有推荐的、更好的或内置的方法吗?如果您没有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程序员不喜欢它:
大约12年前,Python获得了lambda、reduce()、filter()和map(),这是(我相信)一位Lisp黑客的功劳,他错过了它们并提交了工作补丁。但是,尽管有PR值,我认为这些特性应该从python3000中删除
所以现在reduce()。这实际上是我最讨厌的一个,因为除了一些涉及+或*的示例外,几乎每次我看到带有非平凡函数参数的reduce()调用时,我都需要抓起纸笔来绘制实际输入到该函数中的内容,然后才能理解reduce()应该做什么。所以在我看来,reduce()的适用性非常局限于关联运算符,在所有其他情况下,最好显式写出累加循环
从Python 2.6版开始,您可以使用多个参数 如果集合在列表中,则转换为:
u = set.intersection(*setlist)
其中*是一个_列表
请注意,
set.intersection
不是静态方法,但它使用函数表示法应用第一个集合与列表其余部分的交集。因此,如果参数列表为空,则此操作将失败。从2.6开始,设置。交集
可以使用任意多个iterables
>>> 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])
在这里,我提供了一个多集交叉的通用函数,试图利用可用的最佳方法:
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:])
def多个集合相交(*集合):
“”“返回多集交集。”“”
尝试:
返回集合。交点(*集合)
除了TypeError:#这是Python<2.6或没有参数
通过
try:a_set=set[0]
除索引器外:#无参数
返回集()#返回空集
返回reduce(a_set.intersection,set[1:])
Guido可能不喜欢
reduce
,但我有点喜欢它:)显然set。这里需要的是交集,但如果您需要“取所有这些的总和”、“取所有这些的乘积”、“取所有这些的xor”,您需要的是reduce
函数:
from operator import and_
from functools import reduce
print(reduce(and_, [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
或
Jean-François Fabre集合。intesection(*集合列表)的答案无疑是最Pyhtonic的,并且是公认的答案
对于那些希望使用reduce的用户,以下操作也将起作用:
减少(set.intersection,列出集合)
我认为最简单的方法是:
#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])
注意,Guido说使用reduce
仅限于关联运算符,这在本例中适用reduce
通常很难理解,但对于&
来说,这并不坏。请查看有关reduce的有用优化。通常,它可以很好地用于构建列表、集合、字符串等。值得一看的是,当结果
为空时,您可以通过中断循环进行优化。您应该检查集合
的长度,而不是试图访问集合[0]
并捕获索引器。这不是简单的检查<代码>在最终返回时使用了一套
。如果设置了其他设置()
,您不能返回reduce(设置[0],设置[1:])吗?是的,谢谢。代码应该更改,因为如果可以的话,应该避免依赖try
/除外。这是一种代码气味,效率低下,并且可以隐藏其他问题。不,它不能接受零个可重用项。那么,当可能存在零个参数时,该怎么办?在一行中?@RADIOCONTROLED对于在setlist为空时工作的一行,如果setlist else set()
对sol的复杂性有任何评论,请使用u=set.intersection(*setlist)。如上所述?@CKM,确切地说,我们需要事先按大小在setlist
中对集合进行排序,还是该函数为我们这样做?这与“应用列表中第一个集合与其余集合的交集”的语句相矛盾。@RadioControlled没有集合的交集是没有数学定义的,因此这应该失败。请参阅Patrick Suppes的“公理集理论”。在这里,我非常肯定列表的顺序对速度很重要。通过增加列表中相邻集合的大小或减少预期交集大小来排序,以更精确。
#assuming three sets
set1 = {1,2,3,4,5}
set2 = {2,3,8,9}
set3 = {2,10,11,12}
#intersection
set4 = set1 & set2 & set3
print(set4)
set([2])