如何与字典中的值交换键?

问题:如何与字典中的值交换键?

我收到一个字典作为输入,并想返回一个字典,其键将是输入的值,而键的值将是对应的输入键。价值观是独一无二的。

例如,说我的输入是:

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

我希望我的输出是:

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

为了澄清,我希望我的结果等于以下内容:

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

有什么精巧的Pythonic方式可以做到这一点?

I receive a dictionary as input, and would like to to return a dictionary whose keys will be the input’s values and whose value will be the corresponding input keys. Values are unique.

For example, say my input is:

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

I would like my output to be:

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

To clarify I would like my result to be the equivalent of the following:

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

Any neat Pythonic way to achieve this?


回答 0

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())

Python 2:

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

Python 3 (thanks to @erik):

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

回答 1

new_dict = dict(zip(my_dict.values(), my_dict.keys()))
new_dict = dict(zip(my_dict.values(), my_dict.keys()))

回答 2

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

From Python 2.7 on, including 3.0+, there’s an arguably shorter, more readable version:

>>> my_dict = {'x':1, 'y':2, 'z':3}
>>> {v: k for k, v in my_dict.items()}
{1: 'x', 2: 'y', 3: 'z'}

回答 3

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

回答 4

您可以利用dict理解

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

编辑:对于Python 3,请使用a.items()代替a.iteritems()。可以在Python on SO的迭代项目中找到有关它们之间差异的讨论。

You can make use of dict comprehensions:

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

Edited: For Python 3, use a.items() instead of a.iteritems(). Discussions about the differences between them can be found in iteritems in Python on SO.


回答 5

您可以尝试:

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}。新字典只能有一个带有key的项目1
  2. 一个或多个值是不可散列的。例如{'one':[1]}[1]是有效值,但不是有效键。

有关此主题的讨论,请参见python邮件列表上的该线程

You could try:

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

Beware that you cannot ‘reverse’ a dictionary if

  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.
  2. One or more of the values is unhashable. For example {'one':[1]}. [1] is a valid value but not a valid key.

See this thread on the python mailing list for a discussion on the subject.


回答 6

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

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


回答 7

当前的主要答案假设值是唯一的,但并非总是如此。如果值不是唯一的怎么办?您将失去信息!例如:

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']}。这就是最底层的实现。

Python 2.x

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

Python 3.x

def reverse_non_unique_mapping(d):
    dinv = {}
    for k, v in d.items():
        if v in dinv:
            dinv[v].append(k)
        else:
            dinv[v] = [k]
    return dinv

The current leading answer assumes values are unique which is not always the case. What if values are not unique? You will loose information! For example:

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

returns {2: 'b', 3: 'a'}.

The information about 'c' was completely ignored. Ideally it should had be something like {2: ['b','c'], 3: ['a']}. This is what the bottom implementation does.

Python 2.x

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

Python 3.x

def reverse_non_unique_mapping(d):
    dinv = {}
    for k, v in d.items():
        if v in dinv:
            dinv[v].append(k)
        else:
            dinv[v] = [k]
    return dinv

回答 8

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}
new_dict = dict( (my_dict[k], k) for k in my_dict)

or even better, but only works in Python 3:

new_dict = { my_dict[k]: k for k in my_dict}

回答 9

扩展Ilya Prokin响应的另一种方法是实际使用该reversed功能。

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

本质上,您的字典通过(使用.items())进行迭代,其中每个项目都是键/值对,并且这些项目与reversed函数交换。当将其传递给dict构造函数时,它将把它们变成您想要的值/键对。

Another way to expand on Ilya Prokin‘s response is to actually use the reversed function.

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

In essence, your dictionary is iterated through (using .items()) where each item is a key/value pair, and those items are swapped with the reversed function. When this is passed to the dict constructor, it turns them into value/key pairs which is what you want.


回答 10

改善哈维尔答案的建议:

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

而不是d.keys()您只能编写d,因为如果您使用迭代器浏览字典,它将返回相关字典的键。

例如 对于这种行为:

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

Suggestion for an improvement for Javier answer :

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

Instead of d.keys() you can write just d, because if you go through dictionary with an iterator, it will return the keys of the relevant dictionary.

Ex. for this behavior :

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

回答 11

使用字典理解可以轻松完成:

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

Can be done easily with dictionary comprehension:

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

回答 12

dict(map(lambda x: x[::-1], YourDict.items()))

.items()返回的元组列表(key, value)map()遍历列表中的元素并应用于lambda x:[::-1]其每个元素(元组)以将其反转,因此每个元组都将(value, key)在新列表中分散在地图之外。最后,dict()从新列表中做出决定。

dict(map(lambda x: x[::-1], YourDict.items()))

.items() returns a list of tuples of (key, value). map() goes through elements of the list and applies lambda x:[::-1] to each its element (tuple) to reverse it, so each tuple becomes (value, key) in the new list spitted out of map. Finally, dict() makes a dict from the new list.


回答 13

使用循环:-

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

Using 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

回答 14

如果您使用的是Python3,则略有不同:

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

If you’re using Python3, it’s slightly different:

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

回答 15

添加就地解决方案:

>>> 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返回键的视图。如果您使用的是Python2,d.keys()就足够了。

Adding an in-place solution:

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

In Python3, it is critical that you use list(d.keys()) because dict.keys returns a view of the keys. If you are using Python2, d.keys() is enough.


回答 16

Hanan的答案是正确的,因为它涵盖了更一般的情况(其他答案对于没有意识到重复情况的人来说是一种误导)。对Hanan答案的一种改进是使用setdefault:

mydict = {1:a, 2:a, 3:b}   
result = {}
for i in mydict:  
   result.setdefault(mydict[i],[]).append(i)
print(result)
>>> result = {a:[1,2], b:[3]}

Hanan’s answer is the correct one as it covers more general case (the other answers are kind of misleading for someone unaware of the duplicate situation). An improvement to Hanan’s answer is using setdefault:

mydict = {1:a, 2:a, 3:b}   
result = {}
for i in mydict:  
   result.setdefault(mydict[i],[]).append(i)
print(result)
>>> result = {a:[1,2], b:[3]}