我有一个集合列表:
setlist = [s1,s2,s3...]
我想要s1∩s2∩s3…
我可以写一个函数,通过执行一系列成对的s1.intersection(s2),等等。
是否有推荐的、更好的或内置的方法?
我有一个集合列表:
setlist = [s1,s2,s3...]
我想要s1∩s2∩s3…
我可以写一个函数,通过执行一系列成对的s1.intersection(s2),等等。
是否有推荐的、更好的或内置的方法?
当前回答
从Python 2.6版起,你可以使用多个参数来set.intersection(),比如
u = set.intersection(s1, s2, s3)
如果集合在列表中,则转换为:
u = set.intersection(*setlist)
*a_list是列表展开
请注意,set.intersection不是一个静态方法,但它使用函数符号来应用第一个集合与列表其余部分的交集。如果参数列表为空,就会失败。
其他回答
如果你没有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自己:
About 12 years ago, Python aquired lambda, reduce(), filter() and map(), courtesy of (I believe) a Lisp hacker who missed them and submitted working patches. But, despite of the PR value, I think these features should be cut from Python 3000. So now reduce(). This is actually the one I've always hated most, because, apart from a few examples involving + or *, almost every time I see a reduce() call with a non-trivial function argument, I need to grab pen and paper to diagram what's actually being fed into that function before I understand what the reduce() is supposed to do. So in my mind, the applicability of reduce() is pretty much limited to associative operators, and in all other cases it's better to write out the accumulation loop explicitly.
从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])
显然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}
or
print(reduce((lambda x,y: x&y), [{1,2,3},{2,3,4},{3,4,5}])) # = {3}
从Python 2.6版起,你可以使用多个参数来set.intersection(),比如
u = set.intersection(s1, s2, s3)
如果集合在列表中,则转换为:
u = set.intersection(*setlist)
*a_list是列表展开
请注意,set.intersection不是一个静态方法,但它使用函数符号来应用第一个集合与列表其余部分的交集。如果参数列表为空,就会失败。
这里我提供了一个多集交集的通用函数,试图利用可用的最佳方法:
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可能不喜欢减少,但我有点喜欢它:)