如何获得两个以上列表的对称差异?

时间:2019-05-01 16:52:35

标签: python set-operations

我想获取所有列表之间的所有排他元素。因此,如果我有3个列表,例如:

list1 = [1, 3, 2]
list2 = ["a", 1, 3]
list3 = [2, 0]

我的输出应该是:

['a', 0]

我试图对所有列表进行对称差分:

set(list1) ^ set(list2) ^ set(list3)

但这不能很好地工作。

我也尝试过:

def exclusive(*lista):
    excl = set(lista[0])
    for idx in range(len(lista)):
        excl ^= set(lista[idx])
    return excl

与第一种方法的工作原理相同,但没有产生我想要的。

然后我尝试了(set(list1) ^ set(list2)) ^ (set(list2) ^ (set(list3)) 并发现它和我第一次尝试的不一样。

编辑:

我以3个列表为例,但函数采用未定义数量的参数

3 个答案:

答案 0 :(得分:5)

您还可以使用SN1234 Amount 1000 Sum 200 SN3456 Amount 2000 Sum 100 采用非固定方法:

collections.Counter

使用from itertools import chain from collections import Counter res = [k for k, v in Counter(chain(list1, list2, list3)).items() if v==1] print(res) #['a', 0] 将您的列表放在一起,并使用itertools.chain进行计数。仅保留计数为1的那些。


更新:这是一个更好的示例,演示了为什么其他方法不起作用。

Counter

根据您的条件,正确答案是:

list1 = [1, 3, 2]
list2 = ["a", 1, 3]
list3 = [2, 0]
list4 = [1, 4]
all_lists = [list1, list2, list3, list4]

使用print([k for k, v in Counter(chain(*all_lists)).items() if v==1]) #['a', 4, 0]

reduce(set.symmetric_difference, ...)

使用对称差减去交集:

sets = map(set, all_lists)
print(reduce(set.symmetric_difference, sets))
#{0, 1, 4, 'a'}

答案 1 :(得分:0)

您应该从3组的对称差中减去3组的交集,以获得独占项:

set1 = set(list1)
set2 = set(list2)
set3 = set(list3)

(set1 ^ set2 ^ set3) - (set1 & set2 & set3)

所以给定:

list1 = [1,3,2]
list2 = ["a",1,3]
list3 = [2,0,1]

这将返回:

{0, 'a'}

而您对set1 ^ set2 ^ set3的尝试将错误地返回:

{0, 1, 'a'}

答案 2 :(得分:0)

这主要可以通过设置操作来完成,但是我更喜欢@pault中答案的简单性。为了获得任意数量的集合的对称差,可以找到所有集合组合之间的交集,然后从所有集合的并集获得该组合交集的对称差。

from itertools import combinations

def symdiff(*sets):
    union = set()
    union.update(*sets)

    intersect = set()
    for a, b in combinations(sets, 2):
        intersect.update(a.intersection(b))

    return intersect.symmetric_difference(union)

distincts = symdiff(set([1, 3, 2]), set(['a', 1, 3]), set([2, 0]))
print(distincts)
# {0, 'a'}

以下是更好的示例输入,其中集合的简单顺序对称差异不会提供相同的结果。

distincts = symdiff(set([1, 3, 2, 0]), set(['a', 1, 3, 0]), set([2, 0]))
print(distincts)
# {'a'}