paradigm
paradigm

Reputation: 13

Eliminating duplicate valued key from a dict

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

Answers (6)

RoadRunner
RoadRunner

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

rnso
rnso

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

user2390182
user2390182

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

Dawid Dave Kosiński
Dawid Dave Kosiński

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

mrCarnivore
mrCarnivore

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

timgeb
timgeb

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

Related Questions