1

I'm looking for a way to find the unique items between several sets. For example, take these 3 sets.

x = {1, 2}
y = {1, 3}
z = {1, 3, 4, 5}

How can I find the unique items? I'm looking for something like this.

findunique(x, y, z) # {2, 4, 5}

I tried using symmetric_difference with reduce, but that ended up returning {1, 2, 4, 5}.

The only other thing I can think of is to have a dict keep track of how many counts there are for each item, and return only the ones with 1 count. However, that seems very inefficient and unpythonic. What's the "right" way to go about this?

Daffy
  • 841
  • 9
  • 23

2 Answers2

2

Combine the sets into one list with chain. Count the number of occurrences of each item with Counter. Select the items that occur only once and make a set of them.

from collections import Counter
from itertools import chain

sets = x,y,z
{x for x, cnt in Counter(chain.from_iterable(sets)).items() if cnt==1}
#{2, 4, 5}

EDITED based on the comments by @jedwards.

DYZ
  • 55,249
  • 10
  • 64
  • 93
  • Why not simply `{x for x, cnt in Counter(chain(x, y, z)).items() if cnt==1}`? – jedwards Oct 07 '18 at 05:56
  • @jedwards No big difference, but using `from_iterable` is [considered more elegant](https://stackoverflow.com/questions/15004772/what-is-the-difference-between-chain-and-chain-from-iterable-in-itertools). – DYZ Oct 07 '18 at 06:00
  • Is it considered more elegant to needlessly create lists using `map(list, ...)`? – jedwards Oct 07 '18 at 06:00
  • @jedwards That part is indeed redundant. – DYZ Oct 07 '18 at 06:01
  • @DYZ What about star notation? `Counter(chain(*sets))` – Daffy Oct 09 '18 at 01:46
  • @Daffy `chain(*sets)` is simply `chain(x, y, z)` in disguise. So, same answer. – DYZ Oct 09 '18 at 02:08
0

You could flatten the sets after converting them to a single list and then filter it for items with count that equal 1.

lista = [x, y, z]
listb = [j for i in lista for j in i]
print(set(filter(lambda x: listb.count(x) == 1, listb)))
# {2, 4, 5}
vash_the_stampede
  • 4,590
  • 1
  • 8
  • 20