views:

556

answers:

5

Suppose that I need to swap keys for values in dictionary.

This is what I have in mind (Assuming that the values' value is unique):

>>> my_dict = {'x':1, 'y':2, 'z':3}
>>> my_dict2 = {}
>>> for key, val in my_dict.items():
        my_dict2[val] = key

Is there any other efficient way to do it?

+10  A: 
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'}
sunqiang
Not in the original question, I'm just curious what will happen if you had duplicate values in the original dictionary and then swap key/values with this method?
Andre Miller
@Andre Miller: It takes the last occurrence of the particular key: dict(((1,3),(1,2))) == {1:2}
balpha
duplicates will get overwritten with the last encountered dupe.
Christopher
@Andre Miller: And because d.items() returns items in an arbitrary order you get an arbitrary key for duplicate values.
Ants Aasma
I think that it will takes the last key, value pair that it found.It's like a['x'] = 3. Then you set a['x'] = 4.
Selinap
@Andre, I think the later will remove the prior key out of dictfor example {'x':1, 'y':2, 'z':2} -> {1: 'x', 2: 'z'}but the order is not always intuitive
sunqiang
+7  A: 
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}
balpha
A: 

Don't iterate while you modify values. Python may not even let you try.

Here's an easy way to swap:

my_dict2 = dict.fromkeys(my_dict.values(), my_dict().keys())

From http://docs.python.org/library/stdtypes.html#dict.fromkeys

mcandre
This doesn't work. The second argument to dict.fromkeys is a value, not a list of values.
Ants Aasma
Please use the Code Sample formatting, so that its easier to read your answer.
B Johnson
+4  A: 
new_dict = dict (zip(my_dict.values(),my_dict.keys()))
Javier
Are really values() and keys() guaranteed to have the same ordering?
Lennart Regebro
See the ordering note at http://docs.python.org/library/stdtypes.html#dict.items
Chris Boyle
yes, from http://www.python.org/dev/peps/pep-3106/The specification implies that the order in which items are returned by .keys(), .values() and .items() is the same (just as it was in Python 2.x), because the order is all derived from the dict iterator (which is presumably arbitrary but stable as long as a dict isn't modified). but this answer needs call my_dict twice(one for values, one for keys). maybe this is not ideal.
sunqiang
Yes, this answer iterates through the dict twice. sunqiang's answer is preferable for a large dictionary as it only requires one iteration.
Carl Meyer
@Carl Meyer: agree, also, he's using itertools which are a lot better for big datasets. although i wonder if the final dict() call is also streaming, or if it first assembles the whole pairs list
Javier
+3  A: 

that's py3k way:

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