lzc
lzc

Reputation: 1705

Find dictionary keys with duplicate values

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)

Upvotes: 32

Views: 87332

Answers (7)

Joe
Joe

Reputation: 3074

One liner:

from collections import Counter

[k for k, v in some_dict.items() if v in {v for v, count in Counter(some_dict.values()).items() if count > 1}]

Upvotes: 0

HanByul Lee
HanByul Lee

Reputation: 21

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']]

Upvotes: 2

Dr Fabio Gori
Dr Fabio Gori

Reputation: 1195

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

Upvotes: 7

nvd
nvd

Reputation: 3371

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)

Upvotes: 3

user2005685
user2005685

Reputation: 61

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!

Upvotes: 3

abarnert
abarnert

Reputation: 365717

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'}

Upvotes: 38

Blender
Blender

Reputation: 298176

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']
}

Upvotes: 19

Related Questions