Find dictionary keys with duplicate values

Question:

some_dict = {"firstname": "Albert", "nickname": "Albert", "surname": "Likins", "username": "Angel"}

I would like to return the keys of my dict where their value exists for more than one time.

Could some one show me how to implement this?

a_list = []
for k,v in  some_dict.iteritems():
    if v in some_dict.values() and v != some_dict.keys(k):
        a_list.append(k)
Asked By: lzc

||

Answers:

I would start by flipping the keys and values:

flipped = {}

for key, value in d.items():
    if value not in flipped:
        flipped[value] = [key]
    else:
        flipped[value].append(key)

You could do this more efficiently with collections.defaultdict(set). For your dictionary, flipped will look like:

{
    'Albert': ['nickname', 'firstname'],
    'Angel':  ['username'],
    'Likins': ['surname']
}
Answered By: Blender

First, flip the dictionary around into a reverse multidict, mapping each value to all of the keys it maps to. Like this:

>>> some_dict = {"firstname":"Albert","nickname":"Albert","surname":"Likins","username":"Angel"}
>>> rev_multidict = {}
>>> for key, value in some_dict.items():
...     rev_multidict.setdefault(value, set()).add(key)

Now, you’re just looking for the keys in the multidict that have more than 1 value. That’s easy:

>>> [key for key, values in rev_multidict.items() if len(values) > 1]
['Albert']

Except the multidict keys are the original dict values. So, this is each repeated value, not all of the keys matching each repeated value. But you know what is all of the keys matching each repeated value?

>>> [values for key, values in rev_multidict.items() if len(values) > 1]
[{'firstname', 'nickname'}]

Of course that gives you a list of sets. If you want to flatten that into a single list or set, that’s easy. You can use chain.from_iterable, or a nested comprehension, or any of the other usual tricks. For example:

>>> set(chain.from_iterable(values for key, values in rev_multidict.items() if len(values) > 1))
{'firstname', 'nickname'}
Answered By: abarnert

This method does not require neither external libraries nor an if statement:

reverse_dic = {}
for k, v in original_dic.iteritems():
    reverse_dic[v] = reverse_dic.get(v, []) + [k]

The line reverse_dic[v] = reverse_dic.get(v, []) + [k] replaces 4 lines of if-else code

Answered By: Dr Fabio Gori

If your data set isn’t too large, you don’t need reverse multidict. You can use count on dict.values() and return the desired keys by iterating over dict.items().

desired_keys = []

vals = some_dict.values()

for key, value in some_dict.items():
   if vals.count(value) > 1:
        desired_keys.append(key)

Hope this helps!

Answered By: user2005685

This method uses try and for.

original data

original_dict = {"firstname":"Albert", "nickname":"Albert", "surname":"Likins", "username":"Angel"}

code

reverse_dict = {}
for key, value in original_dict.items():
    try:reverse_dict[value].append(key)
    except:reverse_dict[value] = [key]

This method uses dict.get().

reverse_dict = {}
for k, v in original_dict.items():
    reverse_dict[v] = reverse_dict.get(v, []) + [k]

result

>>> reverse_dict
{'Albert': ['firstname', 'nickname'], 'Likins': ['surname'], 'Angel': ['username']}

>>> [value for key, value in reverse_dict.items() if len(value) > 1]
[['firstname', 'nickname']]
Answered By: HanByul Lee

Using “defaultdict”:

from collections import defaultdict

s = [('yellow', 1), ('blue', 2), ('yellow', 3), ('blue', 4), ('red', 1)]
d = defaultdict(list)

for k, v in s:
    d[k].append(v)

for key, value in d.items():
    if len(value) > 1:
        print "key: %s has multiple values: %r" % (key, value)
Answered By: nvd
Categories: questions Tags: ,
Answers are sorted by their score. The answer accepted by the question owner as the best is marked with
at the top-right corner.