如何不使用“|”将两个集合连接到一行中;

假设ST是赋值集。如果不使用连接操作符|,如何找到这两个集合的并集?例如,这个可以找到交集:

S = {1, 2, 3, 4}
T = {3, 4, 5, 6}
S_intersect_T = { i for i in S if i in T }

那么,如何才能在一行中找到两个集合的并集而不使用|呢?

345573 次浏览

假设你也不能使用s.union(t),它等价于s | t,你可以试试

>>> from itertools import chain
>>> set(chain(s,t))
set([1, 2, 3, 4, 5, 6])

或者,如果你想要理解,

>>> {i for j in (s,t) for i in j}
set([1, 2, 3, 4, 5, 6])

如果你说的加入是指工会,试试这个:

set(list(s) + list(t))

这是一个有点hack,但我不能想到一个更好的内衬来做它。

可以对集合使用union方法:set.union(other_set)

注意,它返回一个新的集合,即它不修改自己。

你可以使用or_别名:

>>> from operator import or_
>>> from functools import reduce # python3 required
>>> reduce(or_, [{1, 2, 3, 4}, {3, 4, 5, 6}])
set([1, 2, 3, 4, 5, 6])

假设你有两个列表

 A = [1,2,3,4]
B = [3,4,5,6]

所以你可以找到A Union B,如下所示

 union = set(A).union(set(B))

如果你想找到交点和非交点,你可以这样做

 intersection = set(A).intersection(set(B))
non_intersection = union - intersection

你可以做union或简单的列表理解

[A.add(_) for _ in B]

A有B的所有元素

如果你愿意修改原始集合(在某些情况下你可能想这样做),你可以使用set.update():

S.update(T)

返回值为None,但S将被更新为原始ST的并集。

你可以像这样将这两个集合解压缩成一个:

>>> set_1 = {1, 2, 3, 4}
>>> set_2 = {3, 4, 5, 6}
>>> union = {*set_1, *set_2}
>>> union
{1, 2, 3, 4, 5, 6}

*解包集合。解包是将可迭代对象(例如集合或列表)表示为它产生的每一项。这意味着上面的例子简化为{1, 2, 3, 4, 3, 4, 5, 6},然后再简化为{1, 2, 3, 4, 5, 6},因为集合只能包含唯一的项。

如果你想要加入n集合,最好的性能似乎来自set().union(*list_of_sets),它将返回一个新的集合。

因此,用法可能是:

s1 = {1, 2, 3}
s2 = {2, 3, 4}
s3 = {4, 5, 6}


s1.union(s2, s3) # returns a new set
# Out: {1, 2, 3, 4, 5, 6}
s1.update(s2, s3) # updates inplace

加上上面亚历山大Klimenko的答案,我做了一些简单的测试,如下所示。我相信主要的外卖是,它看起来像更多的随机集合,差异更大的性能。

from random import randint


n = 100


generate_equal = lambda: set(range(10_000))
generate_random = lambda: {randint(0, 100_000) for _ in range(10_000)}


for l in [
[generate_equal() for _ in range(n)],
[generate_random() for _ in range(n)]
]:
%timeit set().union(*l)
%timeit reduce(or_, l)
Out:
# equal sets: 69.5 / 23.6 =~ 3
23.6 ms ± 658 µs per loop (mean ± std. dev. of 7 runs, 10 loops each)
69.5 ms ± 2.57 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
# random sets: 438 / 78.7 =~ 5.6
78.7 ms ± 1.48 ms per loop (mean ± std. dev. of 7 runs, 10 loops each)
438 ms ± 20.8 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)

因此,如果你想要就地更新,最好的性能来自set.update方法,就性能而言,s1.update(s2, s3) = set().union(s2, s3)