获取3个列表之间的差异

9

我正在处理列表的差异。

>>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])

如何获取3个集合之间的差异? 对于3个集合的差异,期望的输出为:
expected output : set([1, 3, 4, 5, 6])

1
是的,预期输出是什么? - NPE
1
@MartijnPieters,那样做怎么能得到结果呢?这将包含“2”。 - Padraic Cunningham
我已经更新了我的问题。 - sam
1
你想要的是 [1, 4, 5, 6] 吗? - Massimo Costa
1
为什么“3??”在三个列表中的两个列表中? - Massimo Costa
显示剩余6条评论
4个回答

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])

(后者可能更可取.)


我们能否使用这种方法找到与3相似的元素? - sam
我是说,如果我想找到3个集合中相似的元素。即2 - sam
@sam:好的,就像我说的,a & b & c - NPE
只要 l 不需要被重复使用,你可以得到:set().union(*l) - set(l.pop()).intersection(*l) 或者如果需要, i = iter(l); set().union(*l) - set(next(i)).intersection(*i) - Jon Clements
هڈ¯èƒ½éœ€è¦په°†iterو›´و”¹ن¸؛next(i, ())ن»¥ه¤„çگ†ç©؛çڑ„lم€‚ - Jon Clements
显示剩余2条评论

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]

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

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])

1

@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'])

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接