Reputation: 1705
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
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
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
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
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
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
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
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