Python 高效计算多个集合的异或/对称差(集合列表)

Python 高效计算多个集合的异或/对称差(集合列表),python,set,xor,set-operations,symmetric-difference,Python,Set,Xor,Set Operations,Symmetric Difference,我有任意数量的Python集,例如 >a={1,2,3} >>>b={3,4,5} >>>c={5,6,7} >>>d={7,8,1} 我想计算它们的“组合”对称差,也就是说,我想对它们进行异或运算: >>a^b^c^d {2, 4, 6, 8} 在我的用例中,我实际上是在处理集合列表: l=[a,b,c,d] >>>l [{1, 2, 3}, {3, 4, 5}, {5, 6, 7}, {1, 7, 8}] 目前,我正在对列表进行迭代,以实现我想要的: >res=l[0]。复制() >>

我有任意数量的Python集,例如

>a={1,2,3}
>>>b={3,4,5}
>>>c={5,6,7}
>>>d={7,8,1}
我想计算它们的“组合”对称差,也就是说,我想对它们进行异或运算:

>>a^b^c^d
{2, 4, 6, 8}
在我的用例中,我实际上是在处理集合列表:

l=[a,b,c,d] >>>l [{1, 2, 3}, {3, 4, 5}, {5, 6, 7}, {1, 7, 8}] 目前,我正在对列表进行迭代,以实现我想要的:

>res=l[0]。复制()
>>>对于l[1:]中的项目:
...     res.symmetric\u difference\u更新(项目)
>>>res
{2, 4, 6, 8}
我想知道是否有一种更有效的方法,理想情况下不需要经过Python for循环。在Python中,集合操作实际上非常快,但我的列表可能会变得相当长,因此具有讽刺意味的是,for循环本身就成了一个瓶颈


编辑(1)

我假设列表中所有集合的每个可能条目在列表中的所有集合中出现的次数不超过两次


编辑(2)

一些基准:

从键入导入列表,设置
从functools导入reduce
从集合导入defaultdict
长度=1_000
数据=[
{idx-1,idx,idx+1}
适用于范围内的idx(3_000,3_000+长度*2,2)
]
def test_loop1(l:List[Set[int]])->Set[int]:
res=l[0]。复制()
对于l[1:]中的项目:
res.symmetric\u difference\u更新(项目)
断言len(res)==len(l)+2
返回res
测试1
:121µs±321 ns

def test_loop2(l:List[Set[int]])->Set[int]:
res=set()
对于l中的项目:
res.symmetric\u difference\u更新(项目)
断言len(res)==len(l)+2
返回res
测试2
:112µs±3.16µs

def test_reduce1(l:List[Set[int]])->Set[int]:
res=减少(设置对称性_差,l)
断言len(res)==len(l)+2
返回res
测试1
:9.89 ms±20.6µs

def test_dict1(l:List[Set[int]])->Set[int]:
"""
一种通用解决方案,允许输入数据中的条目出现两次以上
"""
d=默认dict(int)
对于l中的项目:
输入项目:
d[条目]+=1
res={entry for item in l for item in item if d[entry]==1}
断言len(res)==len(l)+2
返回res

test\u dict1
:695µs±5.11µs

循环的真正问题是在运行列表之前复制列表,即
l[1://code>正在执行列表复制。可以通过使用循环的范围来避免它,从1开始,然后索引到列表中。这样,您就不必分配列表的副本。如果您真的想避免显式循环,可以使用
functools.reduce
执行缩减,但一旦解决了列表复制问题,它可能不会更快。@TomKarzes是的,您是对的。抄袭虽然肤浅,但实际上起到了一定的作用
reduce实际上也比较慢,尽管我可能选择了一种不理想的方式来调用它。我在我的问题中增加了一些基准。