开发者

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
0

上一篇:

下一篇:

精彩评论

暂无评论...
验证码 换一张
取 消

最新问答

问答排行榜