Sorting a Python Dictionary for Fun & Profit

sorted dictionary python overcoded

The Python dictionary is a powerful data structure of key-value pairs indexed by a non-mutable data type. They are inherently unordered though will preserve the order by which items are added. There is no way to sort a python dictionary directly, however, and one must get a little creative.

Fortunately, one can sort a Python dictionary by converting it to a sortable type such as a list. This involves an intermediary step, or a bold one-liner, but is relatively straightforward. I’ll walk you through some basic gotchas, considerations, and notable options. For those here from Google for a quick answer, check out the TL;DR below:

TL;DR – Use the built-in sorted function with a lambda expression as the key.

# Create a dictionary with randomly ordered keys
>>> d = {5: 'f', 3: 'd', 0: 'a', 2: 'c', 6: 'g', 1: 'b'}

# Sort the convert back to dict
>>> d = dict(sorted(d.items()))

>>> print(d)
{0: 'a', 1: 'b', 2: 'c', 3: 'd', 5: 'f', 6: 'g'}

>>> type(d)
<class 'dict'>

Quick Introduction

The Python dictionary is a data structure much like the traditional hash table. It pairs a collection of immutable objects such as an integer, string, or float with paired values that can be mutable or even collections of values.

Python dictionaries are efficient and come packed with tons of useful built-in methods to help with common tasks. Dictionaries are a bit like enums in other languages like Java but have some notable differences.

Sorting A Python Dictionary

Much like the initial TL;DR example, we’re going to start by creating a randomly ordered dictionary. With that, we’ll be able to look at some approaches that work—and some that don’t. Before we dive in, I’ll take a moment and be that guy by advising you to read the official Python dictionary documentation. It does well to lay out many of the methods made available by the Python dictionary structure that we won’t cover here.

# Create a randomly-ordered dictionary
d = {5: 'f', 3: 'd', 0: 'a', 2: 'c', 6: 'g', 1: 'b'}

# Sort the dictionary
sorted(d)

>>> [0, 1, 2, 3, 5, 6]

Whoa! That almost looks like it worked. In this scenario, Python represents dictionaries as keys since (version number citation needed.) Also worth noting is that since PEP448 one can use unpacking directives to produce a list as such:  l = [*d] which would result in a list, though not sorted: [5, 3, 0, 2, 6, 1].

Additionally, Python allows one to use the items method of the dictionary class to return a list of the objects sorted (using the key by default). This is shown in the following code:

# creates the dictionary
d = {5: 'f', 3: 'd', 0: 'a', 2: 'c', 6: 'g', 1: 'b'}

# sorts the dictionary
d = sorted(d.items())

[(0, 'a'), (1, 'b'), (2, 'c'), (3, 'd'), (5, 'f'), (6, 'g')]

Here we see the dictionary has been sorted, using the numeric values as the sorting key. The data is returned as a list of tuple objects representing the key-value pairs. Converting this back to a dictionary is as easy as using the built-in dict(d) syntax as follows:

# convert to a dictionary
d = dict(d)

{0: 'a', 1: 'b', 2: 'c', 3: 'd', 5: 'f', 6: 'g'}

We could also sort the same item based on the values rather than keys by using a lambda function as our key for the sorted function as follows (mixing up the numerical values a bit for a more contrasting example):

# creates the dictionary
d = {10: 'f', 6: 'd', 4: 'a', 2: 'c', 1: 'g', 0: 'b'}

# sorts the dictionary, converts back to dict in 1 line
d = dict(sorted(d.items(), key=lambda x: x[1]))

{4: 'a', 0: 'b', 2: 'c', 6: 'd', 10: 'f', 1: 'g'}

Here we can see an order by values such that a->b->c->d->e->f even though the corresponding numeric keys are wildly out-of-order. Note that Python uses the ordinal value of the characters to determine the sort order.

Sorting with Comprehensions

Python list comprehension is one of the reasons I fell in love with this programming language. It lets one achieve an impressive workload using one-line logic in a highly optimized fashion. For me, it wasn’t immediately clear that Python also accommodated dictionary comprehension out-of-the-box. It does, and we’ll showcase how it can be used to sort dictionaries in Python also!

# Create a randomly-ordered dictionary
d = {5: 'f', 3: 'd', 0: 'a', 2: 'c', 6: 'g', 1: 'b'}

# Sort using dictionary comprehension
d = {k: v for k, v in sorted(d.items())}

>>> {0: 'a', 1: 'b', 2: 'c', 3: 'd', 5: 'f', 6: 'g'}

Here we’ve not only sorted the dictionary by converting it into a list via the sorted(d.items()) approach but we’ve also converted it back to a dictionary. All in one line! Note: we technically converted it into an intermediary generator object, not a list.

This is looking pretty sweet, but let’s take things a step further and introduce a custom key by which our dictionary will be sorted. For example, let’s say we wanted the dictionary sorted by absolute value from the average value of keys.

Let’s see if we can get a one-liner that is up to the task! For this, I’ll use a slightly longer set of values referencing the ASCII lowercase letters made available via the string module:

# Create a randomly-ordered dictionary
alpha = {k: v for k, v in zip(range(len(string.ascii_lowercase)), list(string.ascii_lowercase))}

>>> {0: 'a', 1: 'b', 2: 'c', 3: 'd', 4: 'e', 5: 'f', 6: 'g', 7: 'h', 8: 'i', 9: 'j', 10: 'k', 11: 'l', 12: 'm', 13: 'n', 14: 'o', 15: 'p', 16: 'q', 17: 'r', 18: 's', 19: 't', 20: 'u', 21: 'v', 22: 'w', 23: 'x', 24: 'y', 25: 'z'}

# Order by distance from an calculated value
s = {k: v for k, v in sorted(alpha .items(), key=lambda x: abs(sum(alpha) / len(alpha) - x[0]))}

>>> {12: 'm', 13: 'n', 11: 'l', 14: 'o', 10: 'k', 15: 'p', 9: 'j', 16: 'q', 8: 'i', 17: 'r', 7: 'h', 18: 's', 6: 'g', 19: 't', 5: 'f', 20: 'u', 4: 'e', 21: 'v', 3: 'd', 22: 'w', 2: 'c', 23: 'x', 1: 'b', 24: 'y', 0: 'a', 25: 'z'}

As you can see, the combination of the key argument, a Python lambda function, and dictionary comprehension can do a lot of work. In this case, I’ve sorted a dictionary of the alphabet by proximity to the average position. Why do you ask? Because Python makes it so easy!

Note: Python’s OrderedDict class from the collections module was an often-used alternative to dict objects since it preserved insertion order. Since 3.7 the standard dict object has provided this functionality and has replaced the need for OrderedDict in many cases. OrderedDict still has some performance benefits in some cases and shouldn’t be discounted entirely in my opinion.

Gotchas

Python dictionaries can use a tuple as a key — but that tuple cannot contain a mutable object. For example, tuples are themselves immutable but may contain a structure like a list or an object.

Final Thoughts

Python’s dictionary structure is an incredible tool for hash-mapping and I use them all the time. I use them commonly when I’m storing credentials locally or in the cloud, working with collections where query times are more important than order, and especially when serializing data. Translating between Python dictionaries and JSON-formatted strings is phenomenally easy (here’s looking at you Java.)

Even when the use-case for dictionaries is strong, I find a need to get a sorted version of a collection or, at the very least, derive some value from the sorted order of keys. Using the methods outlined in this article I find that tasks can be accomplished effectively—often in a one-liner. I hope this article has been helpful and urge everyone to recognize we’ve only covered a fraction of the use cases, implications of use, and methods of the Python dictionary data type. There is much more to know about them!

Zαck West
Full-Stack Software Engineer with 10+ years of experience. Expertise in developing distributed systems, implementing object-oriented models with a focus on semantic clarity, driving development with TDD, enhancing interfaces through thoughtful visual design, and developing deep learning agents.