Welcome, guest | Sign In | My Account | Store | Cart

Dictionaries map keys to values. Looking up a value is as simple as typing: mydict[key]. But what if you want to look up a key? The following one liner returns a new dictionary with the keys and values swapped:

Python, 6 lines
1
2
3
4
5
6
# Invert a dictionary
mydict = {"Apple": "red", "Banana": "yellow", "Carrot": "orange"}

inverted_dict = dict([[v,k] for k,v in mydict.items()])

print inverted_dict["red"]

Sometimes the keys and values in a dictionary have equal importance as references. Inverting a dictionary allows you to reverse the mapping and use a value to look up a key. NOTE: This only works if there are no duplicate values in the dictionary. If there are common values only the last key will be preserved once swapped. One way to deal with duplicate values is to turn all keys with a common value into a list when you invert the dictionary. I haven't found a shortcut for that method yet.

10 comments

Ian Bollinger 17 years, 12 months ago  # | flag

My own solution. DictInvert = lambda d: dict(zip(d.values(), d.keys()))

Raymond Hettinger 17 years, 11 months ago  # | flag

Think iterator! Both of the solutions could benefit from using the iterator forms: iteritems, iterkeys, itervalues, izip.

Jason Drew 16 years, 11 months ago  # | flag

Iterator and common values. Here's an iterator version that does turn all keys with a common value into a list when you invert the dictionary.

def dictinvert(d):
    inv = {}
    for k, v in d.iteritems():
        keys = inv.setdefault(v, [])
        keys.append(k)
    return inv

E.g.

>>> dictinvert({'a': 55, 'b': 55, 'c': 88})

{88: ['c'], 55: ['a', 'b']}

Christian Holtje 15 years, 7 months ago  # | flag

keys() and values() will always be in order. Will the values of keys() and values() always be in the same order?

That is, your little lambda won't reorder the relationship between value and key?

Ciao!

Philip Sternberg 14 years, 10 months ago  # | flag

Keys must be hashable. Just a small note: the keys to a dictionary must be hashable, so in the above, this must be enforced. For types that can be converted to strings, this can be the best method, but there can clearly be some loss of functionality.

Pete Forman 13 years, 2 months ago  # | flag

Generator expressions were introduced in Python 2.4, so the intermediate list is no longer required:

inverted_dict = dict([v,k] for k,v in mydict.items())

Jason's comment manages duplicate values. It may be simpler to disallow them:

assert len(inverted_dict) == len(mydict), 'duplicate value in mydict'
Pete Forman 13 years, 2 months ago  # | flag

My comment missed out Raymond's advice, it should have been:

inverted_dict = dict([v,k] for k,v in mydict.iteritems())
Uwe Schmitt 12 years, 11 months ago  # | flag

I think this his is the shortest one:

dict(zip(*zip(*mydict.items())[::-1]))
Uwe Schmitt 12 years, 11 months ago  # | flag

... this is not the shortest one, but maybe the most crpytic :-)

Francis Carr 12 years ago  # | flag

If you need to maintain the inverse mapping across many updates and changes, then these one-shot one-liners must be re-computed many times. To cope with that situation, I just added Recipe 576968 with a python dict subclass.

Created by Joel Lawhead on Mon, 17 Nov 2003 (PSF)
Python recipes (4591)
Joel Lawhead's recipes (3)
Python Cookbook Edition 2 (117)

Required Modules

  • (none specified)

Other Information and Tasks