Я хочу получить все эксклюзивные элементы между всеми моими списками. Так что, если у меня есть 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 ответа
Вы также можете воспользоваться подходом без установки, используя 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
, чтобы сгладить ваши списки вместе, и используйте 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]
Используя reduce(set.symmetric_difference, ...)
:
sets = map(set, all_lists)
print(reduce(set.symmetric_difference, sets))
#{0, 1, 4, 'a'}
Используя симметричную разность минус пересечение:
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'}
Это можно сделать в первую очередь с помощью операций над множествами, но я предпочитаю простоту ответа от @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'}
Вы должны вычесть пересечение 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'}
Похожие вопросы
Связанные вопросы
Новые вопросы
python
Python - это многопарадигмальный, динамически типизированный, многоцелевой язык программирования. Он разработан для быстрого изучения, понимания и использования, а также для обеспечения чистого и единообразного синтаксиса. Обратите внимание, что Python 2 официально не поддерживается с 01.01.2020. Тем не менее, для вопросов о Python, связанных с версией, добавьте тег [python-2.7] или [python-3.x]. При использовании варианта Python (например, Jython, PyPy) или библиотеки (например, Pandas и NumPy) включите его в теги.