Explain Codes LogoExplain Codes Logo

Reverse / invert a dictionary mapping

python
dataframe
defaultdict
pythonic
Anton ShumikhinbyAnton Shumikhin·Dec 14, 2024
TLDR

Need to invert a Python dictionary by swapping keys and values? No sweat. Use {value: key for key, value in original_dict.items()}. This slice of wizardry will create an inverted dictionary where your old values are now keys (and vice versa). Do make sure your values are unique though - duplicates will be ruthlessly overwritten.

Here’s the bare bones:

# Welcome to the world of one-liners! inverted_dict = {v: k for k, v in {'a': 1, 'b': 2, 'c': 3}.items()}

And voila, inverted_dict pops out as {1: 'a', 2: 'b', 3: 'c'}.

Duplicate values handling

When you've got a dictionary with duplicate values, it's like a room full of twins. Flip them around, and things can get pretty chaotic. To restore sanity, we can store all keys that map to the same value in an elegant for loop with defaultdict:

from collections import defaultdict # Here's our innocent looking dictionary original_dict = {'a': 1, 'b': 2, 'c': 1} inverted_dict = defaultdict(list) for key, value in original_dict.items(): # Join the party, duplicates! inverted_dict[value].append(key)

You'll now have an inverted_dict that looks like this: {1: ['a', 'c'], 2: ['b']}.

Python 2 got your back

If you're still partying with the dinosaurs on Python 2, replace .items() with .iteritems(). Just like the difference between a house party and a Zoom party - it'll save you much-needed memory space.

# Python 2, we still love you inverted_dict = {v: k for k, v in original_dict.iteritems()}

For those who enjoy dancing between Python 2 and 3, here's a universal groove:

# Night at the Python 2/3 disco inverted_dict = dict((v, k) for k, v in original_dict.items())

Order in the inverted court

Since Python 3.7+, dictionary order is like a faithful Labrador - it sticks by your side. Values are kept orderly, meaning you can rely on the sequence of keys while inverting:

# Meet our orderly dictionary ordered_dict = {'first': 1, 'second': 2, 'third': 3} # Time to flip it, but keep the order though inverted_ordered_dict = {v: k for k, v in ordered_dict.items()}

inverted_ordered_dict maintains the order: {1: 'first', 2: 'second', 3: 'third'}.

Large dictionaries? No problem

Think large dictionaries are monstrous? Fear not - a generator expression will slay those memory issues in no time:

# It's not the size, but how you handle it! gen_expression = ((v, k) for k, v in large_dict.items()) inverted_dict = dict(gen_expression)

You're now creating tuple pairs on the fly and not cramming memory with everything at once.

How about custom classes?

If you're dealing with a subclass of a dictionary, you might still want to hold onto the specific type after the flip. All you need is the class constructor:

# Custom class, because we're fancy class MyDict(dict): pass # The diva of dictionaries original_custom_dict = MyDict(a=1, b=2) # Flip it, but keep the custom class inverted_custom_dict = MyDict((v, k) for k, v in original_custom_dict.items())

Not only is inverted_custom_dict fabulous, but it's also still an instance of MyDict.

Modern, fast and Pythonic

When it comes to flipping dictionaries, Python 3 syntax is your chisel and hammer, crafted for creating modern, cleaner and more efficient code. Always keep it on your toolbelt.

The joy of exploration

Nothing beats spending an afternoon poring over the Python documentation, diving into the hidden corners of how dictionaries are implemented and optimized in Python. Join the club - becoming a Python dictionary guru is just a few lines of code away.