smarter "reverse" of a dictionary in python (acc for some of values being the same)?
def revert_开发者_JAVA技巧dict(d):
rd = {}
for key in d:
val = d[key]
if val in rd:
rd[val].append(key)
else:
rd[val] = [key]
return rd
>>> revert_dict({'srvc3': '1', 'srvc2': '1', 'srvc1': '2'})
{'1': ['srvc3', 'srvc2'], '2': ['srvc1']}
This obviously isn't simple exchange of keys with values: this would overwrite some values (as new keys) which is NOT what I'm after.
If 2 or more values are the same for different keys, keys are supposed to be grouped in a list.
The above function works, but I wonder if there is a smarter / faster way?
That looks pretty good. You could simplify it a little bit by using defaultdict
:
import collections
def revert_dict(d):
rd = collections.defaultdict(list)
for key, value in d.iteritems():
rd[value].append(key)
return rd
Probably not as efficient, but:
ks, vs = old_dict.items()
new_dict = dict((v, [k for k in ks if old_dict[k] == v]) for v in set(vs))
An alternative approach. Not sure if this is faster (I doubt that).
from itertools import groupby
old_dict = {'srvc3': '1', 'srvc2': '1', 'srvc1': '2'}
funcval = d.__getitem__
new_dict = dict((val, list(keys)) for val, keys in \
groupby(sorted(d.iterkeys(), key=funcval), funcval))
# new_dict:
# {'1': ['srvc3', 'srvc2'], '2': ['srvc1']}
Your initial code is certainly not bad (readable) although I would probably have written it like this (mostly personal preference, really):
def revert_dict(d):
rd = {}
for key, val in d.items():
try:
rd[val].append(key)
except KeyError:
rd[val] = [key]
return rd
def invertDictionary(d):
rd = {}
for x,y in d.iteritems():
if y in rd.keys():
rd[y].append(x)
else:
rd[y] = [x]
return rd
I find this most readable to myself. Any downsides?
def revert_dict(d):
rd = {}
for key,val in d.iteritems():
rd[val] = rd.get(val,[]) + [key]
return rd
print revert_dict({'srvc3': '1', 'srvc2': '1', 'srvc1': '2',
'srvc4': '8', 'srvc5': '2', 'srvc6': '2',
'srvc7': '77', 'srvc8': '1', 'srvc9': '2',
'srvc10': '3', 'srvc11': '1'})
result
{'1': ['srvc11', 'srvc3', 'srvc2', 'srvc8'], '77': ['srvc7'], '3': ['srvc10'], '2': ['srvc6', 'srvc5', 'srvc1', 'srvc9'], '8': ['srvc4']}
also:
def revert_dict(d):
rd = {}
for key,val in d.iteritems():
rd[val] = rd[val]+ [key] if val in rd else [key]
return rd
精彩评论