Вопрос по dictionary, python – Python: лучший способ обмена ключами со значениями в словаре?

70

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

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

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

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

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

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

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

Любой аккуратный Pythonian способ достичь этого?

Спасибо

Увидетьstackoverflow.com/questions/1087694/… на идентичный вопрос, на который есть хороший ответ, если вы используете Python 3 Stephen Edmonds
возможный дубликатPython reverse / inverse a mapping Cory
Python не является Perl, Python не является Ruby. Читаемость имеет значение. Разреженный лучше, чем плотный. Учитывая это, все методы этих ответов просто плохи & # x2122 ;; тот, о котором идет речь, - лучший путь. o0'.
@ Стефан: см. Второй ответ с наибольшим количеством голосов, он такой же, как принятый в вопросе, с которым вы связаны. Толпа предпочла другой ответ, хотя ... Roee Adler

Ваш Ответ

16   ответов
4

Предложение по улучшению ответа Хавьера:

dict(zip(d.values(),d))

Вместоd.keys() ты можешь написать простоdпотому что, если вы пройдете по словарю с помощью итератора, он вернет ключи соответствующего словаря.

Ex. для этого поведения:

d = {'a':1,'b':2}
for k in d:
 k
'a'
'b'
1

loop:-

newdict = {} #Will ,contain reversed key:value pairs.

for key, value in zip(my_dict.keys(), my_dict.values()):
    # Operations on key/value can also be performed.
    newdict[value] = key
110

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())
Для Python3 это было быres = {v:k for k,v in a.items()}.
код python2 работает ... но понимание списка отсутствует[ а также], для понимания списка не требуется[ а также]?
@HananShteingart: заявленные в вопросе значения являются уникальными. Пожалуйста, создайте отдельный пост с вопросом для вашего случая (и, желательно, разместите ссылку здесь для других людей).
Что если значения не являются уникальными? Тогда ключи должны быть списком ... например: d = {'a': 3, 'b': 2, 'c': 2} {v: k для k, v в d.iteritems ( )} {2: 'b', 3: 'a'} должно быть {2: ['' b ',' c '], 3:' a '}
Хотя это кажется правильным, полезно добавить объяснение того, как это работает, а не просто код.
1

>>> d = {1: 'one', 2: 'two', 3: 'three', 4: 'four'}
>>> for k in list(d.keys()):
...     d[d.pop(k)] = k
... 
>>> d
{'two': 2, 'one': 1, 'four': 4, 'three': 3}

В Python3 очень важно, чтобы вы использовалиlist(d.keys()) так какdict.keys возвращаетview из ключей. Если вы используете Python2,d.keys() достаточно.

1

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

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

Помните, что вы не можете «повернуть вспять»; словарь, если

More than one key shares the same value. For example {'one':1,'two':1}. The new dictionary can only have one item with key 1. One or more of the values is unhashable. For example {'one':[1]}. [1] is a valid value but not a valid key.

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

Лиори уже предоставил это решение, но спасибо Roee Adler
+1 я добавил примечание о уникальности значений, спасибо Roee Adler
Также +1 за примечание о том, что значения в оригинальном dict уникальны; в противном случае вы будете перезаписаны на "перевернутый"; dict ... и это (я только что нашел это за мою цену) может вызвать хитрые ошибки в вашем коде!
8

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

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
это должен быть правильный ответ, так как он охватывает более общий случай
14
new_dict = dict( (my_dict[k], k) for k in my_dict)

new_dict = { my_dict[k]: k for k in my_dict}
На самом деле Dict Понимания (PEP 274) работать с Python 2.7 также.
9

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

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

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

30
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'}
@Andre Miller: требуется последнее вхождение определенного ключа: dict (((1,3), (1,2))) == {1: 2}
Я думаю, что это займет последнюю пару ключ, значение, которое он нашел. Это похоже на ['x'] = 3. Затем вы устанавливаете ['x'] = 4.
дубликаты будут перезаписаны последним обнаруженным дублированием.
Не в первоначальном вопросе, мне просто любопытно, что произойдет, если у вас будут повторяющиеся значения в исходном словаре, а затем поменяйте местами ключ / значения этим методом?
@Andre Miller: А поскольку d.items () возвращает элементы в произвольном порядке, вы получаете произвольный ключ для повторяющихся значений.
2
dict(map(lambda x: x[::-1], YourDict.items()))

.items() возвращает список кортежей(key, value). map() просматривает элементы списка и применяетlambda x:[::-1] каждому его элементу (кортежу) обратить его, так что каждый кортеж становится(value, key) в новый список выплюнуло из карты. В заключение,dict() делает диктат из нового списка.

Можете ли вы объяснить, как это работает?
.items () возвращает список кортежей (ключ, значение). map () просматривает элементы списка и применяетlambda x:[::-1] каждому его элементу (кортежу), чтобы обратить его, так что каждый кортеж становится (значение, ключ) в новом списке, выделенном из карты. Наконец, dict () делает диктат из нового списка.
1

Может быть легко сделано с пониманием словаря:

{d[i]:i for i in d}
43

включая 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'}
25

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

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

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

12

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

Вы правы. Ваш ответ более эффективен.
dict не гарантирует, что его values () и keys () будут возвращать элементы в том же порядке. Кроме того, keys (), values () и zip () возвращают список, где итератора будет достаточно.
nosklo, что если другой поток изменяет словарь?
@liori: Ты не прав. dict гарантирует, что его values () и keys () будут в одном и том же порядке, если вы, конечно, не изменяете dict между вызовами values () и keys (). Документация гласит, что здесь: (прочитайте раздел «Примечание»:docs.python.org/library/stdtypes.html#dict.items) & quot; Если items (), keys (), values (), iteritems (), iterkeys () и itervalues () вызываются без промежуточных модификаций словаря, списки будут напрямую соответствовать. & quot;
Хорошо, тогда я ошибаюсь ... Я не проверял онлайн-документы. Спасибо, что указали на это.
49
new_dict = dict (zip(my_dict.values(),my_dict.keys()))
См. Примечание к заказу наdocs.python.org/library/stdtypes.html#dict.items
@Carl Meyer: согласен, он также использует itertools, которые намного лучше подходят для больших наборов данных. хотя мне интересно, если последний вызов dict () также потоковый, или он сначала собирает весь список пар
Да, этот ответ повторяет диктовку дважды. Ответ Sunqiang предпочтителен для большого словаря, поскольку он требует только одну итерацию.
Действительно ли values () и keys () имеют одинаковый порядок?
да, изpython.org/dev/peps/pep-3106 Спецификация подразумевает, что порядок, в котором элементы возвращаются с помощью .keys (), .values () и .items (), одинаков (так же, как это было в Python 2.x), потому что порядок является производным от dict итератор (который, по-видимому, произвольный, но устойчивый до тех пор, пока диктовка не модифицирована). но этот ответ должен вызвать my_dict дважды (один для значений, один для ключей). может быть, это не идеально.

Похожие вопросы