views:

3647

answers:

7

Given a dictionary likeso:

map = { 'a': 1, 'b':2 }

How can one invert this map to get:

inv_map = { 1: 'a', 2: 'b' }

+5  A: 

Try this :

inv_map = dict(zip(map.values(), map.keys()))

or alternatively

inv_map = dict((map[k], k) for k in map)

or using python 3.0's dict comprehensions

inv_map = {map[k] : k for k in map}
sykora
Would this be slwoer than Heikogerlach's solution because it has to iterate through the map twice - once for the values, once for the keys? Thanks!
Brian M. Hunt
Based on my own testing using the timeit class, surprisingly, my first and third methods take roughly half as long as my own second method and Heikogerlach's solution. I didn't do any major testing, just a few test cases.
sykora
Do values() and keys() guarantee that they will return their items in the same order? If not, then you wouldn't end up with the mapping that you started with.
davidavr
Both values() and keys() will return them in the same order. The order itself is according to python's internal storage of the keys, but the order will not change between values() and keys() (Unless of course the dictionary itself changes in between the calls).
sykora
@sykora: how do you know that?
recursive
@recursive: I read it somewhere, but when I searched again, the only link I could turn up was this one (http://www.python.org/dev/peps/pep-3106/), the original proposal to turn keys(), values() and items() into iterators. I'll keep looking.
sykora
@sykora: unless it's documented in the dict class, I think you are depending on an implementation detail which is risky.
davidavr
Argh, why do I always find the answer in the last place I look? http://docs.python.org/3.0/library/stdtypes.html#dictionary-view-objects . Everybody satisfied? :)
sykora
+27  A: 

Assuming that the values in the dict are unique:

dict((v,k) for k, v in map.iteritems())
unbeknown
+11  A: 

for python3:

inv_map = {v:k for k, v in map.items()}
SilentGhost
+7  A: 

If the values in map aren't unique:

for k, v in map.iteritems():
    inv_map[v] = inv_map.get(v, [])
    inv_map[v].append(k)
Robert Rossney
`from collections import defaultdict; inv_map = defaultdict(list)` will let you skip the second line and go straight to appending.
gotgenes
A: 
def inverse_mapping(f):
    return f.__class__(map(reversed, f.items()))
fs
+1  A: 

Or if the values aren't unique and you're a little harcore:

inv_map = \
    dict( \
            (v, [k for (k, xx) in filter(lambda (key, value): value == v, map.items())]) \
        for v in set(map.values()))
pcv