Reputation: 13
I have the following dictionary,
>>> names
{1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
What is the best way to eliminate keys with duplicate entries based on the first entry in the value i.e 1 and 3 are duplicates because of 'c1' and 2 and 4 are duplicates because of 'c2'?
I would like the final output to be something like this
>>> uniqueNames
{1: ('c1', 1), 2: ('c2', 2) }
Upvotes: 1
Views: 100
Reputation: 26315
You could use collections.defaultdict
to group what you want, and only take the first value:
from collections import defaultdict
d = {1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
groups = defaultdict(list)
for num1, (entry, num2) in d.items():
groups[entry].append((num1, num2))
# defaultdict(<class 'list'>, {'c1': [(1, 1), (3, 3)], 'c2': [(2, 2), (4, 4)]})
result = {v[0][0]:(k, v[0][1]) for k, v in groups.items()}
print(result)
# {1: ('c1', 1), 2: ('c2', 2)}
Or even with itertools.groupby
:
grouped = [list(g) for _, g in groupby(sorted(d.items(), key = lambda x: x[1][0]), key = lambda x: x[1][0])]
# [[(1, ('c1', 1)), (3, ('c1', 3))], [(2, ('c2', 2)), (4, ('c2', 4))]]
result = {k: v for (k, v) in [x[0] for x in grouped]}
print(result)
# {1: ('c1', 1), 2: ('c2', 2)}
Upvotes: 0
Reputation: 24535
Try:
ulist = [] # unique-list
outdict = {} # dict for output
for i in names.items(): # i will be as: (1, ('c1', 1))
if i[1][0] not in ulist:
ulist.append(i[1][0]) # add unique item to unique-list
outdict[i[0]] = i[1] # add entry to output dict
print(outdict)
Output:
{1: ('c1', 1), 2: ('c2', 2)}
Upvotes: 1
Reputation: 73450
Here is the cryptic one-liner such questions tend to elicit:
unique_names = dict({i[1][0]: i for i in names.items()}.values())
If you want to guarantee to keep the smallest key:
unique_names = dict({i[1][0]: i for i in sorted(names.items(), reverse=True)}.values())
Collects the old items as values to the keys to be uniquified and builds a new dict from the items that remain as values in said dict.
Upvotes: 4
Reputation: 901
Do a set of first tuple values and then knowing what values are unique you can pop keys from the dict.
>>> temp = {1: ('a', '1'), 2: ('b', '2'), 3: ('a', '3'), 4: ('b', '4')}
>>> uniques = set()
>>> uniquedict = {}
>>> for key, value in temp.iteritems():
... if value[0] not in uniques:
... uniques.update(value[0])
... uniquedict[key]=value
...
>>>
>>> uniquedict
{1: ('a', '1'), 2: ('b', '2')}
edit: this is for python 2.7, @mrCarnivore answer is for python 3
Upvotes: 0
Reputation: 5078
You could solve it like this:
names = {1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
values_set = set()
unique_names = {}
for key, value in names.items():
if value[0] not in values_set:
values_set.add(value[0])
unique_names[key] = value
print(unique_names)
Upvotes: 0
Reputation: 78680
Similar to how you would eliminate duplicates in a regular list while keeping the list's order.
The only real difference here is that dictionaries have no order, which means that iteration order through names.items
is arbitrary so you will keep an arbitrary key-value pair with a unique first item for the value-tuple.
>>> names = {1: ('c1', 1), 2: ('c2', 2), 3: ('c1', 3), 4: ('c2', 4)}
>>>
>>> seen = set()
>>> unique_names = {}
>>>
>>> for k, (v0, v1) in names.items():
... if v0 not in seen:
... unique_names[k] = (v0, v1)
... seen.add(v0)
...
>>> unique_names
{1: ('c1', 1), 2: ('c2', 2)}
Upvotes: 5