Python 如何获得两个以上列表的对称差?
我想在我的所有列表之间获得所有独占元素。因此,如果我有3个列表,如:Python 如何获得两个以上列表的对称差?,python,set-operations,Python,Set Operations,我想在我的所有列表之间获得所有独占元素。因此,如果我有3个列表,如: list1 = [1, 3, 2] list2 = ["a", 1, 3] list3 = [2, 0] set(list1) ^ set(list2) ^ set(list3) 我的输出应该是: ['a', 0] 我尝试对所有列表进行对称差分,如: list1 = [1, 3, 2] list2 = ["a", 1, 3] list3 = [2, 0] set(list1) ^ set(list2) ^ set(li
list1 = [1, 3, 2]
list2 = ["a", 1, 3]
list3 = [2, 0]
set(list1) ^ set(list2) ^ set(list3)
我的输出应该是:
['a', 0]
我尝试对所有列表进行对称差分,如:
list1 = [1, 3, 2]
list2 = ["a", 1, 3]
list3 = [2, 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个集合的对称差中减去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'}
然而,您尝试设置1^set2^set3将错误返回:
{0, 1, 'a'}
您还可以使用
集合采用非集合方法。计数器:
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
将列表平铺在一起,并使用Counter
对发生的事件进行计数。仅保留计数为1的事件
更新:下面是一个更好的示例,演示了其他方法不起作用的原因
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]
使用减少(set.symmetric_difference,…)
:
使用对称差减去交点:
set1 = set(list1)
set2 = set(list2)
set3 = set(list3)
set4 = set(list4)
print((set1 ^ set2 ^ set3 ^ set4) - (set1 & set2 & set3 & set4))
#{0, 1, 4, 'a'}
这主要可以通过集合运算来实现,但我更喜欢简单的答案。为了获得任意数量集合的对称差,可以找到所有集合组合之间的交集,然后从所有集合的并集中获得该组合交集的对称差
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'}
“不好用”是什么意思?set(list1)^set(list2)^set(list3)
工作得很好。如果您想要一个列表作为结果,请将结果转换为列表:list(set(list1)^…)
@Aran Fey不,它不能完全正常工作。3个集合上的对称差分将返回3个集合的交集以及独占项。更改输入值将更好地突出显示2个以上集合的顺序对称差分所导致的问题。例如,尝试建议的解决方案按此顺序输入以下内容:[1,3,2,0]
,[a',1,3,0]
,[2,0]
。在这种情况下,唯一应产生的排他元素是“a”@DYZ我更喜欢在集合中。我只是想要元素组。我仍然认为这在一般情况下不起作用-我更新了我的答案,以包括一个示例来演示这一点。编辑:在我更新的示例中,问题是set1&set2&set3&set4
返回一个空集。是的,我应该注意到该方法仅适用于3个集合。它不适用于函数如果一个列表中有两个或多个相等的元素:[1]
和[1,2,2]
将返回一个空列表,而不是[2,2]
@MykolaZotko这是一个正确的说法,但这不是我解释问题要求的方式,因为OP在尝试将列表转换为集合。@pault我转换列表是为了消除重复问题elements@pault我几乎能理解你的答案,但不要反驳@DanielMuñoz-是dict
的子类,因此Counter.items()
返回键值对的视图(有点像列表)。对于Counter
,键是元素,值是计数。