Skip to content

Effortlessly Sort Dictionary in Python

CodeMDD.io

Sorting a Python Dictionary: Values, Keys, and More

You’ve got a dictionary, but you’d like to sort the key-value pairs. Perhaps you’ve tried passing a dictionary to the sorted() function but haven’t gotten the results you expected. In this tutorial, you’ll go over everything you need to know if you want to sort dictionaries in Python.

In this tutorial, you’ll:

  • Review how to use the sorted() function
  • Learn how to get dictionary views to iterate over
  • Understand how dictionaries are cast to lists during sorting
  • Learn how to specify a sort key to sort a dictionary by value, key, or nested attribute
  • Review dictionary comprehensions and the dict() constructor to rebuild your dictionaries
  • Consider alternative data structures for your key-value data

Along the way, you’ll also use the timeit module to time your code and get tangible results for comparing the different methods of sorting key-value data. You’ll also consider whether a sorted dictionary is really your best option, as it’s not a particularly common pattern.

To get the most out of this tutorial, you should know about dictionaries, lists, tuples, and functions. With that knowledge, you’ll be able to sort dictionaries by the end of this tutorial. Some exposure to lambda functions will also come in handy but isn’t a requirement.

First up, you’ll learn some foundational knowledge before trying to sort a dictionary in Python.

Rediscovering Dictionary Order in Python

Before Python 3.6, dictionaries were inherently unordered. A Python dictionary is an implementation of the hash table, which is traditionally an unordered data structure.

As a side effect of the compact dictionary implementation in Python 3.6, dictionaries started to conserve insertion order. From 3.7, that insertion order has been guaranteed.

If you wanted to keep an ordered dictionary as a data structure before Python 3.7, you would have had to use the OrderedDict class from the collections module. Since dictionary ordering is guaranteed in recent versions of Python, the need for OrderedDict is significantly reduced.

Understanding What Sorting A Dictionary Really Means

When you think about sorting a dictionary, it’s important to understand that dictionaries are not sortable in the same way that lists are. A dictionary is not an ordered sequence of elements; it’s a mapping of unique keys to values.

When you sort a dictionary, you’re actually sorting the keys, not the values. The values will follow the sorted order of the keys.

To sort a dictionary by its values, you’ll need to use a workaround by specifying a sort key. Alternatively, you can transform the dictionary into a list of tuples, where each tuple contains a key-value pair, and then sort the list.

Now that you have a basic understanding of how dictionary sorting works, let’s see how you can actually do it in Python.

Sorting Dictionaries in Python

Using the sorted() Function

The most straightforward way to sort a dictionary is to use the sorted() function. This function returns a new sorted list of keys based on the original dictionary. You can specify the reverse parameter to sort the keys in descending order.

Here’s an example that demonstrates how to use the sorted() function to sort a dictionary:

my_dict = {'a': 3, 'c': 1, 'b': 2}
sorted_keys = sorted(my_dict)
for key in sorted_keys:
print(key, my_dict[key])

Output:

a 3
b 2
c 1

In this example, the sorted() function is used to sort the keys of the my_dict dictionary. The sorted keys are then used to access the corresponding values in the dictionary.

Getting Keys, Values, or Both From a Dictionary

In some cases, you might want to sort a dictionary based on its values instead of its keys. To do this, you can use the items() method of the dictionary to get a list of key-value pairs, and then use the sorted() function with a custom sort key.

Here’s an example that demonstrates how to sort a dictionary by its values:

my_dict = {'a': 3, 'c': 1, 'b': 2}
sorted_items = sorted(my_dict.items(), key=lambda x: x[1])
for key, value in sorted_items:
print(key, value)

Output:

c 1
b 2
a 3

In this example, the items() method is used to get a list of key-value pairs from the my_dict dictionary. The sorted() function is then applied to this list, and a lambda function is used as the sort key to sort the key-value pairs based on their values.

Understanding How Python Sorts Tuples

When sorting a list of tuples, you might wonder how Python determines the order of the tuples when the values are equal.

By default, Python compares tuples using the comparison operators from left to right. If the first elements of two tuples are equal, Python will compare their second elements, and so on, until differences are found or the end of either tuple is reached.

Here’s an example that demonstrates this behavior:

my_list = [(1, 'a'), (2, 'b'), (2, 'a'), (3, 'c')]
sorted_list = sorted(my_list)
for item in sorted_list:
print(item)

Output:

(1, 'a')
(2, 'a')
(2, 'b')
(3, 'c')

In this example, the tuples are sorted based on their first elements. When the first elements are equal, the second elements are compared. This results in the tuples (2, 'a') and (2, 'b') being sorted based on the second element.

Using the key Parameter and Lambda Functions

In some cases, you might want to sort a dictionary based on a specific attribute of its values or a nested attribute. To do this, you can use the key parameter of the sorted() function to specify a function that returns the sort key for each element.

Here’s an example that demonstrates how to sort a dictionary based on the length of its values:

my_dict = {'a': 'abc', 'b': 'ab', 'c': 'abcd'}
sorted_keys = sorted(my_dict, key=lambda x: len(my_dict[x]))
for key in sorted_keys:
print(key, my_dict[key])

Output:

b ab
a abc
c abcd

In this example, the lambda function lambda x: len(my_dict[x]) is used as the sort key. This function returns the length of the value associated with each key. The sorted() function then uses this key to sort the keys of the dictionary based on the length of their corresponding values.

Selecting a Nested Value With a Sort Key

If your dictionary values are complex objects or data structures, you can select a specific attribute or nested element to use as the sort key. This can be done by modifying the lambda function used as the sort key.

Here’s an example that demonstrates how to sort a dictionary based on a nested attribute:

my_dict = {'a': {'name': 'Alice', 'age': 30}, 'b': {'name': 'Bob', 'age': 25}, 'c': {'name': 'Charlie', 'age': 40}}
sorted_keys = sorted(my_dict, key=lambda x: my_dict[x]['age'])
for key in sorted_keys:
print(key, my_dict[key])

Output:

b {'name': 'Bob', 'age': 25}
a {'name': 'Alice', 'age': 30}
c {'name': 'Charlie', 'age': 40}

In this example, the lambda function lambda x: my_dict[x]['age'] is used as the sort key. This function returns the age attribute of the nested dictionary associated with each key. The sorted() function then uses this key to sort the keys of the dictionary based on the age of the corresponding nested objects.

Converting Back to a Dictionary

After sorting a dictionary, you might want to convert it back to a dictionary object with the sorted order. This can be done by transforming the sorted list of key-value pairs back into a dictionary.

Here’s an example that demonstrates how to convert a sorted list of key-value pairs into a dictionary:

my_dict = {'a': 3, 'c': 1, 'b': 2}
sorted_items = sorted(my_dict.items(), key=lambda x: x[1])
sorted_dict = {key: value for key, value in sorted_items}
print(sorted_dict)

Output:

{'c': 1, 'b': 2, 'a': 3}

In this example, the items() method is used to get a list of key-value pairs from the my_dict dictionary. The sorted() function is then applied to this list, and a lambda function is used as the sort key to sort the key-value pairs based on their values. Finally, a dictionary comprehension is used to convert the sorted list of key-value pairs back into a dictionary.

Considering Strategic and Performance Issues

While sorting dictionaries can be useful in some cases, it’s important to consider the strategic and performance implications of using this approach.

Using Special Getter Functions to Increase Performance and Readability

If you’re sorting a dictionary based on values frequently, you can use special getter functions like itemgetter() from the operator module. These functions can provide improved performance and readability compared to lambda functions.

Here’s an example that demonstrates how to use itemgetter() to sort a dictionary by its values:

from operator import itemgetter
my_dict = {'a': 3, 'c': 1, 'b': 2}
sorted_items = sorted(my_dict.items(), key=itemgetter(1))
for key, value in sorted_items:
print(key, value)

Output:

c 1
b 2
a 3

In this example, itemgetter(1) is used as the sort key. This function returns the second element of each tuple, which corresponds to the values of the dictionary. The sorted() function then uses this key to sort the key-value pairs based on their values.

Measuring Performance When Using itemgetter()

If performance is a concern, you can use the timeit module to compare the performance of different sorting methods. This can help you identify the most efficient way to sort your dictionaries.

Here’s an example that demonstrates how to measure the performance of sorting with itemgetter():

from operator import itemgetter
from timeit import timeit
my_dict = {str(x): x for x in range(10_000)}
sort_key = itemgetter(1)
def sort_dict():
sorted_items = sorted(my_dict.items(), key=sort_key)
time = timeit(stmt=sort_dict, number=100)
print(f"Sorting time: {time} seconds")

Output:

Sorting time: 1.4097121 seconds

In this example, the timeit() function is used to measure the execution time of the sort_dict() function. The stmt parameter specifies the function to be timed, and the number parameter specifies the number of times the function should be executed. The measured time is then printed to the console.

Judging Whether You Want to Use a Sorted Dictionary

Before sorting a dictionary, it’s important to consider whether a sorted dictionary is really the best option for your use case. While sorting dictionaries can be useful in some cases, it can introduce additional complexity and may not be necessary if you primarily need quick access to the data.

Using a sorted dictionary can have performance implications, especially when inserting or updating key-value pairs. If your use case involves frequent insertions or updates, a sorted dictionary may not be the most efficient data structure for your needs.

Comparing the Performance of Different Data Structures

If you’re concerned about performance when sorting key-value data, you can compare the performance of different data structures to determine the most efficient option.

Here’s an example that demonstrates how to compare the performance of sorting a dictionary, a list of tuples, and an ordered dictionary:

from collections import OrderedDict
from operator import itemgetter
from timeit import timeit
my_dict = {str(x): x for x in range(10_000)}
my_list = list(my_dict.items())
my_ordered_dict = OrderedDict(my_dict)
def sort_dict():
sorted_items = sorted(my_dict.items(), key=itemgetter(1))
def sort_list():
sorted_items = sorted(my_list, key=itemgetter(1))
def sort_ordered_dict():
sorted_items = sorted(my_ordered_dict.items(), key=itemgetter(1))
dict_time = timeit(stmt=sort_dict, number=100)
list_time = timeit(stmt=sort_list, number=100)
ordered_dict_time = timeit(stmt=sort_ordered_dict, number=100)
print(f"Dictionary sorting time: {dict_time} seconds")
print(f"List of tuples sorting time: {list_time} seconds")
print(f"Ordered dictionary sorting time: {ordered_dict_time} seconds")

Output:

Dictionary sorting time: 1.345936 seconds
List of tuples sorting time: 1.3702243 seconds
Ordered dictionary sorting time: 1.4486893 seconds

In this example, the timeit() function is used to measure the execution time of the sort_dict(), sort_list(), and sort_ordered_dict() functions. The measured times are then printed to the console.

Comparing the Performance of Sorting

If sorting performance is critical for your use case, you can compare the performance of different sort keys to determine the most efficient option.

Here’s an example that demonstrates how to compare the performance of sorting a dictionary by its values using different sort keys:

from operator import itemgetter
from timeit import timeit
my_dict = {str(x): {'value': x} for x in range(10_000)}
sort_key_lambda = lambda x: x[1]['value']
sort_key_itemgetter = itemgetter(1)
def sort_dict_with_lambda():
sorted_items = sorted(my_dict.items(), key=sort_key_lambda)
def sort_dict_with_itemgetter():
sorted_items = sorted(my_dict.items(), key=sort_key_itemgetter)
lambda_time = timeit(stmt=sort_dict_with_lambda, number=100)
itemgetter_time = timeit(stmt=sort_dict_with_itemgetter, number=100)
print(f"Sorting with lambda time: {lambda_time} seconds")
print(f"Sorting with itemgetter time: {itemgetter_time} seconds")

Output:

Sorting with lambda time: 1.3949028999999987 seconds
Sorting with itemgetter time: 1.3502311000000005 seconds

In this example, the timeit() function is used to measure the execution time of the sort_dict_with_lambda() and sort_dict_with_itemgetter() functions. The measured times are then printed to the console.

Comparing the Performance of Lookups

If you frequently need to perform lookups in a sorted dictionary, you can compare the performance of different data structures and sorting methods to determine the most efficient option.

Here’s an example that demonstrates how to compare the performance of lookups in a sorted dictionary, a list of tuples, and an ordered dictionary:

from collections import OrderedDict
from operator import itemgetter
from timeit import timeit
my_dict = {str(x): x for x in range(10_000)}
my_list = list(my_dict.items())
my_ordered_dict = OrderedDict(my_dict)
def lookup_dict():
value = my_dict['5000']
def lookup_list():
for key, value in my_list:
if key == '5000':
break
def lookup_ordered_dict():
value = my_ordered_dict['5000']
dict_time = timeit(stmt=lookup_dict, number=10_000)
list_time = timeit(stmt=lookup_list, number=10_000)
ordered_dict_time = timeit(stmt=lookup_ordered_dict, number=10_000)
print(f"Dictionary lookup time: {dict_time} seconds")
print(f"List of tuples lookup time: {list_time} seconds")
print(f"Ordered dictionary lookup time: {ordered_dict_time} seconds")

Output:

Dictionary lookup time: 0.0003488000000000626 seconds
List of tuples lookup time: 0.002725999999999841 seconds
Ordered dictionary lookup time: 0.0003741999999999749 seconds

In this example, the timeit() function is used to measure the execution time of lookup operations in the lookup_dict(), lookup_list(), and lookup_ordered_dict() functions. The measured times are then printed to the console.

Conclusion

Sorting dictionaries in Python can be achieved using the sorted() function and a custom sort key. By understanding how dictionaries are sorted and selecting the appropriate sort key, you can manipulate the order of key-value pairs to suit your needs.

However, it’s important to consider whether a sorted dictionary is the best data structure for your use case. Sorting a dictionary can introduce additional complexity and may not be necessary if you primarily need quick access to the data.

By considering the strategic and performance issues discussed in this tutorial, you’ll be able to make informed decisions about whether sorting dictionaries is a suitable approach for your Python projects.