I want to get all exclusive elements between all my lists. So if I have 3 lists like:
list1 = [1, 3, 2]
list2 = ["a", 1, 3]
list3 = [2, 0]
My output should be:
['a', 0]
I tried to do symmetric differencing with all of the lists like:
set(list1) ^ set(list2) ^ set(list3)
But this doesn´t work well.
Also I tried:
def exclusive(*lista):
excl = set(lista[0])
for idx in range(len(lista)):
excl ^= set(lista[idx])
return excl
That works the same as the first method but it doesn´t produce what I want.
Then I tried (set(list1) ^ set(list2)) ^ (set(list2) ^ (set(list3))
and found that it's not the same as what I first tried.
EDIT:
I give 3 list as an example but function take undifined number of arguments
You could also take a non-set approach using 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]
Use itertools.chain
to flatten your lists together and use Counter
to count the occurrences. Keep only those where the count is 1.
Update: Here is a better example that demonstrates why the other methods do not work.
list1 = [1, 3, 2]
list2 = ["a", 1, 3]
list3 = [2, 0]
list4 = [1, 4]
all_lists = [list1, list2, list3, list4]
Based on your criteria, the correct answer is:
print([k for k, v in Counter(chain(*all_lists)).items() if v==1])
#['a', 4, 0]
Using reduce(set.symmetric_difference, ...)
:
sets = map(set, all_lists)
print(reduce(set.symmetric_difference, sets))
#{0, 1, 4, 'a'}
Using the symmetric difference minus the intersection:
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'}