获取三个列表之间的差异

9 投票
4 回答
5346 浏览
提问于 2025-04-18 17:23

我正在研究列表之间的差异。

>>a = [1, 2, 3]
>>b = [2, 4, 5]
>>c = [3, 2, 6]

两个集合之间的对称差异可以通过以下方式实现:

>>z = set(a).symmetric_difference(set(b))
>>print z
>>set([1, 3, 4, 5])

那么,如何计算三个集合之间的差异呢?对于三个集合的差异,期望的输出是:

expected output : set([1, 3, 4, 5, 6])

4 个回答

0

@NPE 这个回答并没有按预期工作,因为它依赖于之前操作的结果。在你的例子中,你可以看到数字 '3' 从第一组到第三组重叠,但仍然被包含在结果中。

>>> a = set(('a','b','c')) 
>>> b = set(('c','d','e'))
>>> c = set(('e','f','g'))
>>> (a | b | c) - (a & b & c)
set(['a', 'c', 'b', 'e', 'd', 'g', 'f'])

这种情况发生是因为它先计算了 'a' 和 'b' 的交集,然后再计算与 'c' 的交集。要解决这个问题,你可以:

>>> (a | b | c) - ((a & b) | (a & c) | (b & c))
set(['a', 'b', 'd', 'g', 'f'])

另外,为了节省两次操作,你可以先计算前两组的对称差,再与第三组合并,然后计算第一组和第三组以及第二组和第三组交集的并集的差。

>>> ((a ^ b) | c) - ((a & c) | (b & c))
set(['a', 'b', 'd', 'g', 'f'])
4

这样怎么样:

>>> a = [1, 2, 3]
>>> b = [2, 4, 5]
>>> c = [3, 2, 6]
>>> z1 = set(a).symmetric_difference(set(b))
>>> z2 = set(b).symmetric_difference(set(c))
>>> print z1.union(z2)
set([1, 3, 4, 5, 6])
5

这个怎么样:

def difflists(*lists):
    sets = map(set, lists)
    return set.union(*sets) - set.intersection(*sets)

print difflists(a, b, c)    # set([1, 3, 4, 5, 6])

如果你想排除那些出现超过一次的元素,可以这样做:

from itertools import chain
from collections import Counter

def difflists(*lists):
    items = Counter(it for lst in lists for it in lst)
    return [it for it, count in items.iteritems() if count == 1]

print difflists(a, b, c)    # [1, 4, 5, 6]

这个方法可以接受任意数量的列表。

19

只需要把交集从并集中减去:

In [1]: a = set([1, 2, 3])

In [2]: b = set([2, 4, 5])

In [3]: c = set([3, 2, 6])

In [4]: (a | b | c) - (a & b & c)
Out[4]: set([1, 3, 4, 5, 6])

或者,想要更一般化地处理一组集合:

In [10]: l = [a, b, c]

In [11]: reduce(set.union, l) - reduce(set.intersection, l)
Out[11]: set([1, 3, 4, 5, 6])

或者:

In [13]: set.union(*l) - set.intersection(*l)
Out[13]: set([1, 3, 4, 5, 6])

(后者可能更好一些。)

撰写回答