Python 求按原点分隔的两个集合的对称差

Python 求按原点分隔的两个集合的对称差,python,performance,python-3.x,set,Python,Performance,Python 3.x,Set,我有两套: >>> a = {1,2,3} >>> b = {2,3,4,5,6} 我想得到两个带有非公共元素的新集合,第一个集合包含a中的元素,第二个集合包含b中的元素,比如({1},{4,5,6}),或者类似的: >>> c = a&b # Common elements >>> d = a^b # Symmetric difference >>> (a-b, b-a) ({1}, {4, 5

我有两套:

>>> a = {1,2,3}
>>> b = {2,3,4,5,6}
我想得到两个带有非公共元素的新集合,第一个集合包含
a
中的元素,第二个集合包含
b
中的元素,比如
({1},{4,5,6})
,或者类似的:

>>> c = a&b # Common elements
>>> d = a^b # Symmetric difference
>>> (a-b, b-a)
({1}, {4, 5, 6})
>>> (a-c, b-c)
({1}, {4, 5, 6})
>>> (a&d, b&d)
({1}, {4, 5, 6})
我的问题是,我将在大量的sha1哈希上使用它,我担心性能。有效地做到这一点的正确方法是什么


注:
a
b
将有大约95%的元素是通用的,1%将在
a
中,4%在
b
中,我在问题中提到的方法具有以下性能:

>>> timeit.timeit('a-b; b-a', 'a=set(range(0,1500000)); b=set(range(1000000, 2000000))', number=1000)
135.45828826893307
>>> timeit.timeit('c=a&b; a-c; b-c', 'a=set(range(0,1500000)); b=set(range(1000000, 2000000))', number=1000)
189.98522938665735
>>> timeit.timeit('d=a^b; a&d; b&d', 'a=set(range(0,1500000)); b=set(range(1000000, 2000000))', number=1000)
238.35084129583106
t = timeit.Timer(lambda: symmetric_diff(a,b))
>>> t.timeit(1000)
542.3225249653769
所以最有效的方法似乎是使用
(a-b,b-a)
方法

我将此作为参考发布,以便其他答案会添加新方法,而不是比较我发现的方法


Python实现的函数 出于好奇,我尝试实现自己的python函数来实现这一点(在预排序迭代器上工作):

与其他方法相比,此方法的性能非常低:

>>> timeit.timeit('a-b; b-a', 'a=set(range(0,1500000)); b=set(range(1000000, 2000000))', number=1000)
135.45828826893307
>>> timeit.timeit('c=a&b; a-c; b-c', 'a=set(range(0,1500000)); b=set(range(1000000, 2000000))', number=1000)
189.98522938665735
>>> timeit.timeit('d=a^b; a&d; b&d', 'a=set(range(0,1500000)); b=set(range(1000000, 2000000))', number=1000)
238.35084129583106
t = timeit.Timer(lambda: symmetric_diff(a,b))
>>> t.timeit(1000)
542.3225249653769

因此,除非在某个地方实现了其他方法(一些用于处理集合的库),否则我认为使用两个集合的差异是最有效的方法。

a-b,b-a
是我过去这样做的方法,但这是为了可读性而不是性能。你为什么不试试其中的几种方法,然后在
timeit
中逐一运行呢?我认为你无法击败
a-b,b-a
。Python所要做的就是计算名称
a
b
,然后用
-
进行二进制减法(您可以用查看确切的细分)。然而,创建新集合的实际函数是用C编写的,这将比用Python编写的任何函数都要好。我认为
a-b,b-a
将是O(n),无论如何,我无法想象有任何方法比
O(n)
更好。用一次迭代而不是两次迭代不会改变复杂性。无论如何,这是一个有趣的问题,在更新关系数据库上的多对多时,我经常需要这样做,以确定要添加/修改/删除哪些元素