Python: лучший способ обмена ключами со значениями в словаре? - PullRequest
77 голосов
/ 23 июня 2009

Я получаю словарь в качестве ввода и хотел бы вернуть словарь, ключи которого будут значениями ввода, а значение - соответствующими клавишами ввода. Значения уникальны.

Например, скажите, что мой ввод:

a = dict()
a['one']=1
a['two']=2

Я бы хотел, чтобы мой вывод был:

{1: 'one', 2: 'two'}

Чтобы уточнить, я бы хотел, чтобы мой результат был эквивалентен следующему:

res = dict()
res[1] = 'one'
res[2] = 'two'

Любой изящный Pythonian способ достигнуть этого?

Спасибо

Ответы [ 16 ]

120 голосов
/ 23 июня 2009

Python 2:

res = dict((v,k) for k,v in a.iteritems())

Python 3 (спасибо @erik):

res = dict((v,k) for k,v in a.items())
51 голосов
/ 06 июля 2009
new_dict = dict (zip(my_dict.values(),my_dict.keys()))
44 голосов
/ 06 июля 2009

Начиная с версии Python 2.7, включая 3.0+, существует значительно более короткая и читаемая версия:

>>> my_dict = {'x':1, 'y':2, 'z':3}
>>> {v: k for k, v in my_dict.items()}
{1: 'x', 2: 'y', 3: 'z'}
30 голосов
/ 06 июля 2009
In [1]: my_dict = {'x':1, 'y':2, 'z':3}

In [2]: dict((value, key) for key, value in my_dict.iteritems())
Out[2]: {1: 'x', 2: 'y', 3: 'z'}
26 голосов
/ 04 августа 2013

Вы можете использовать диктовку :

res = {v: k for k, v in a.iteritems()}

Отредактировано: для Python 3 используйте a.items() вместо a.iteritems(). Обсуждение различий между ними можно найти в итеритах в Python на SO.

18 голосов
/ 23 июня 2009

Вы можете попробовать:

d={'one':1,'two':2}
d2=dict((value,key) for key,value in d.iteritems())
d2
  {'two': 2, 'one': 1}

Помните, что вы не можете "перевернуть" словарь, если

  1. Более одного ключа имеют одинаковое значение. Например {'one':1,'two':1}. Новый словарь может содержать только один элемент с ключом 1.
  2. Одно или несколько значений не подлежат изменению. Например {'one':[1]}. [1] является допустимым значением, но не действительным ключом.

См. эту ветку в списке рассылки python для обсуждения данной темы.

14 голосов
/ 06 июля 2009
new_dict = dict( (my_dict[k], k) for k in my_dict)

или даже лучше, но работает только в Python 3:

new_dict = { my_dict[k]: k for k in my_dict}
13 голосов
/ 23 июня 2009

res = dict(zip(a.values(), a.keys()))

10 голосов
/ 10 марта 2016

Еще один способ раскрыть вопрос Илья Прокин - фактически использовать функцию reversed.

dict(map(reversed, my_dict.items()))

По сути, ваш словарь повторяется (используя .items()), где каждый элемент является парой ключ / значение, и эти элементы меняются местами с помощью функции reversed. Когда это передается конструктору dict, он превращает их в пары значение / ключ, что вам и нужно.

9 голосов
/ 04 августа 2017

Текущий ведущий ответ предполагает, что значения уникальны, что не всегда так. Что если значения не являются уникальными? Вы потеряете информацию! Например:

d = {'a':3, 'b': 2, 'c': 2} 
{v:k for k,v in d.iteritems()} 

возвращает {2: 'b', 3: 'a'}.

Информация о 'c' была полностью проигнорирована. В идеале это должно быть что-то вроде {2: ['b','c'], 3: ['a']}. Это то, что делает нижняя реализация.

def reverse_non_unique_mapping(d):
    dinv = {}
    for k, v in d.iteritems():
        if v in dinv:
            dinv[v].append(k)
        else:
            dinv[v] = [k]
    return dinv
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...