умнее "обратный" словарь в python (учитывая, что некоторые значения совпадают)? - PullRequest
5 голосов
/ 14 января 2011
def revert_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']}

Это, очевидно, не простой обмен ключами со значениями: это перезаписывает некоторые значения (как новые ключи), что НЕ то, что я ищу.

Если 2 или более значений одинаковы для разных ключей, ключи должны быть сгруппированы в списке.

Вышеприведенная функция работает, но мне интересно, есть ли более умный / быстрый способ?

Ответы [ 5 ]

8 голосов
/ 14 января 2011

Это выглядит довольно хорошо.Вы можете немного упростить это, используя defaultdict:

import collections

def revert_dict(d):
    rd = collections.defaultdict(list)

    for key, value in d.iteritems():
        rd[value].append(key)

    return rd
0 голосов
/ 16 февраля 2011
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'})

результат

{'1': ['srvc11', 'srvc3', 'srvc2', 'srvc8'], '77': ['srvc7'], '3': ['srvc10'], '2': ['srvc6', 'srvc5', 'srvc1', 'srvc9'], '8': ['srvc4']}

также:

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 голосов
/ 16 февраля 2011
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 

Я считаю это наиболее читабельным для себя.Есть минусы?

0 голосов
/ 14 января 2011

Возможно, не так эффективно, но:

ks, vs = old_dict.items()
new_dict = dict((v, [k for k in ks if old_dict[k] == v]) for v in set(vs))
0 голосов
/ 14 января 2011

Альтернативный подход.Не уверен, что это быстрее (я сомневаюсь в этом).

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

Ваш исходный код, конечно, неплох (читабелен), хотя я бы, вероятно, написал его так (в основном из личных предпочтений):

def revert_dict(d):
    rd = {}
    for key, val in d.items():
        try:
            rd[val].append(key)
        except KeyError:
            rd[val] = [key]
    return rd
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...