Skip to content

Effortlessly Sort and Access Dictionary in Python

[

Sorting a Python Dictionary: Values, Keys, and More

by Ian Currie data-structures intermediate

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 higher-order functions, such as 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.6, you needed to use the collections.OrderedDict class instead.

Understanding What Sorting A Dictionary Really Means

When you think about sorting a list, you might think about ordering its elements in ascending or descending order. But what does it mean to sort a dictionary?

In Python, a dictionary consists of key-value pairs. When you sort a dictionary, you’re actually sorting the keys of the dictionary. Once you have the sorted keys, you can access the corresponding values of the dictionary.

Sorting a dictionary is different from sorting a list or a tuple because dictionary keys are unique and unordered.

Sorting Dictionaries in Python

Now that you have a clear understanding of dictionaries and their order, let’s dive into the different methods of sorting dictionaries in Python.

Using the sorted() Function

One way to sort a dictionary is to use the built-in sorted() function. The sorted() function takes an iterable as an argument and returns a new sorted list.

To sort a dictionary, you can pass its keys to the sorted() function. Here’s an example:

fruits = {'apple': 4, 'banana': 2, 'orange': 3}
sorted_keys = sorted(fruits)
for key in sorted_keys:
print(key, fruits[key])

Output:

apple 4
banana 2
orange 3

In this example, you pass the fruits dictionary’s keys to the sorted() function, which returns a new list of sorted keys. Then, you iterate over the sorted keys and access the corresponding values from the fruits dictionary.

Keep in mind that the sorted() function returns a list, not a dictionary. If you need to perform further operations on the sorted key-value pairs, you can convert them back to a dictionary using a dictionary comprehension or the dict() constructor, which we’ll cover later in this tutorial.

Getting Keys, Values, or Both From a Dictionary

Sometimes you might want to sort a dictionary based on its values instead of its keys. In Python, you can use the sorted() function with the key parameter to specify a custom sort order.

To sort a dictionary by its values, you can pass the dict.items() method as the key parameter to the sorted() function. Here’s an example:

fruits = {'apple': 4, 'banana': 2, 'orange': 3}
sorted_by_value = sorted(fruits.items(), key=lambda x: x[1])
for key, value in sorted_by_value:
print(key, value)

Output:

banana 2
orange 3
apple 4

In this example, you use the dict.items() method to get a collection of key-value pairs from the fruits dictionary. Then, you pass this collection to the sorted() function along with a lambda function as the key parameter. The lambda function specifies that the sorting should be based on the second element (value) of each key-value pair.

If you want to sort the dictionary in reverse order, you can add the reverse=True parameter to the sorted() function. For example:

sorted_by_value = sorted(fruits.items(), key=lambda x: x[1], reverse=True)

This will sort the dictionary in descending order of its values.

If you want to sort a dictionary by both its keys and values, you can pass a tuple as the key parameter. The tuple specifies multiple levels of sorting. Here’s an example:

fruits = {'apple': 4, 'banana': 2, 'orange': 3}
sorted_by_key_and_value = sorted(fruits.items(), key=lambda x: (x[0], x[1]))
for key, value in sorted_by_key_and_value:
print(key, value)

Output:

apple 4
banana 2
orange 3

In this example, you pass a tuple (x[0], x[1]) as the key parameter to the sorted() function. This will first sort the dictionary by its keys (x[0]) and then within each key, sort by its values (x[1]).

Understanding How Python Sorts Tuples

The sorted() function uses Python’s built-in comparison function, __lt__(), to compare elements while sorting. By default, this function compares elements lexicographically. This means that it compares the first element of each tuple, then the second, and so on, until a difference is found.

If you want to customize the sorting behavior, you can define your own comparison function and use it as the key parameter in the sorted() function.

Using the key Parameter and Lambda Functions

You can use the key parameter in the sorted() function to specify a function that will be called on each element during sorting. The return value of this function will be used to determine the order of the elements.

sorted_list = sorted(iterable, key=function)

In the previous examples, you used lambda functions as the key parameter to specify custom sorting behavior. Lambda functions are anonymous functions that can be defined in a single line.

You can also define your own named functions and use them as the key parameter. This can be useful if you need to reuse the sorting logic in multiple places.

Here’s an example using a named function:

def sort_by_length(word):
return len(word)
words = ['apple', 'banana', 'orange']
sorted_by_length = sorted(words, key=sort_by_length)
print(sorted_by_length)

Output:

['apple', 'orange', 'banana']

In this example, you define a function sort_by_length() that takes a word as an argument and returns its length. Then, you pass this function as the key parameter to the sorted() function. The sorting is based on the length of each word.

Selecting a Nested Value With a Sort Key

You can sort a dictionary based on a nested attribute or value by using a lambda function as the key parameter. The lambda function can access the nested attribute using cascading attribute accessors or dictionary indexing.

Here’s an example:

people = [{'name': 'John', 'age': 32}, {'name': 'Alice', 'age': 28}, {'name': 'Bob', 'age': 35}]
sorted_by_age = sorted(people, key=lambda x: x['age'])
for person in sorted_by_age:
print(person)

Output:

{'name': 'Alice', 'age': 28}
{'name': 'John', 'age': 32}
{'name': 'Bob', 'age': 35}

In this example, you use a lambda function lambda x: x['age'] as the key parameter to the sorted() function. The lambda function accesses the nested attribute x['age'] of each person dictionary and uses it for the sorting.

Converting Back to a Dictionary

As mentioned earlier, the sorted() function returns a list, not a dictionary. If you need to convert the sorted key-value pairs back to a dictionary, you can use a dictionary comprehension or the dict() constructor.

Here’s an example using a dictionary comprehension:

fruits = {'apple': 4, 'banana': 2, 'orange': 3}
sorted_dict = {key: fruits[key] for key in sorted(fruits)}
print(sorted_dict)

Output:

{'apple': 4, 'banana': 2, 'orange': 3}

In this example, you create a new dictionary sorted_dict using a dictionary comprehension. The comprehension iterates over the sorted keys of the fruits dictionary and assigns the corresponding values to the keys in the new dictionary.

Alternatively, you can use the dict() constructor with a list of tuples:

sorted_dict = dict(sorted(fruits.items()))

Both approaches will give you a sorted dictionary based on the keys.

Considering Strategic and Performance Issues

Sorting a dictionary may not always be the best solution for your specific use case. Sorting can have strategic and performance implications that you need to consider.

Using Special Getter Functions to Increase Performance and Readability

When using the sorted() function with the key parameter, you can define a helper function that extracts the sorting key from each element. This can make your code more readable and also improve performance by avoiding repeated attribute access or dictionary indexing.

Here’s an example using a helper function:

def get_age(person):
return person['age']
people = [{'name': 'John', 'age': 32}, {'name': 'Alice', 'age': 28}, {'name': 'Bob', 'age': 35}]
sorted_by_age = sorted(people, key=get_age)

In this example, you define a helper function get_age() that takes a person dictionary as an argument and returns the 'age' key. Then, you pass this helper function as the key parameter to the sorted() function. The sorting is now based on the result of the helper function instead of accessing person['age'] directly.

Measuring Performance When Using itemgetter()

If you’re working with large dictionaries or have strict performance requirements, you might want to consider using the operator.itemgetter() function instead of lambda functions as the key parameter.

The operator.itemgetter() function returns a callable object that can be used to extract a specific element from each element in an iterable. This can be more efficient than using lambda functions, especially for large datasets.

Here’s an example:

from operator import itemgetter
fruits = {'apple': 4, 'banana': 2, 'orange': 3}
sorted_by_value = sorted(fruits.items(), key=itemgetter(1))

In this example, you import the itemgetter() function from the operator module. Then, you pass itemgetter(1) as the key parameter to the sorted() function. This will sort the dictionary based on the second element (value) of each key-value pair.

Judging Whether You Want to Use a Sorted Dictionary

While sorting a dictionary can be useful in certain situations, it’s not a particularly common pattern. In most cases, you’ll find more efficient and maintainable solutions by using other data structures, such as lists, tuples, or sets.

Consider the trade-offs of sorting a dictionary, including the performance implications and whether the sorted order needs to be maintained over time. If sorting is a critical requirement for your use case, make sure to carefully evaluate the different sorting methods and their impact on your application’s performance.

Comparing the Performance of Different Data Structures

If you’re dealing with large datasets or performance-critical applications, it’s important to compare the performance of different data structures. Sorting a dictionary can have different performance characteristics compared to sorting other data structures, such as lists or tuples.

You can use the timeit module to measure the execution time of your code and compare the performance of different approaches. By benchmarking your code, you can make informed decisions about which data structure and sorting method to use in your specific use case.

Comparing the Performance of Sorting

Sorting a dictionary can be an expensive operation, especially for large dictionaries. The time complexity of sorting is typically considered to be O(n log n), where n is the number of elements in the dictionary.

To compare the performance of different sorting methods, you can use the timeit module to measure the execution time of your code. Here’s an example using the timeit module to compare dictionary sorting methods:

import timeit
setup = """
fruits = {'apple': 4, 'banana': 2, 'orange': 3}
"""
sort_keys = """
sorted_keys = sorted(fruits)
"""
sort_items = """
sorted_items = sorted(fruits.items(), key=lambda x: x[1])
"""
print("Sorting keys:", timeit.timeit(stmt=sort_keys, setup=setup, number=1000000))
print("Sorting items:", timeit.timeit(stmt=sort_items, setup=setup, number=1000000))

Output:

Sorting keys: 0.4025986999999998
Sorting items: 1.8406351999999996

In this example, you define two different sorting methods sort_keys and sort_items using the setup string. Then, you use the timeit.timeit() function to measure the execution time of each sorting method. The number parameter specifies the number of times each method is executed.

Keep in mind that the actual performance can vary depending on factors such as the size of the dictionary, the specific sorting method used, and the hardware on which the code is running. Make sure to benchmark your code with realistic data and evaluate the performance for your specific use case.

Comparing the Performance of Lookups

In addition to sorting performance, it’s also important to consider the performance of lookups in a sorted dictionary compared to other data structures.

The time complexity of dictionary lookups is typically considered to be O(1) on average, while the time complexity of list or tuple lookups is O(n), where n is the number of elements in the data structure. This means that dictionary lookups are generally more efficient than list or tuple lookups.

However, when using a sorted dictionary, the time complexity of lookups can be affected. While the overall lookup time is still considered to be O(1), the lookup time for a specific key might be slower due to the sorting operation.

Keep this performance trade-off in mind when considering whether to use a sorted dictionary or another data structure for your specific use case.

Conclusion

In this tutorial, you’ve learned how to sort dictionaries in Python and consider the strategic and performance implications of sorting. You can use the built-in sorted() function with a custom key parameter to sort dictionaries based on their keys, values, or nested attributes. You’ve also learned how to convert the sorted key-value pairs back to a dictionary using a dictionary comprehension or the dict() constructor.

Sorting a dictionary can be useful in certain situations, but it’s important to consider alternative data structures and their performance characteristics. You can use the timeit module to measure the performance of your code and compare different sorting methods.

By understanding the techniques and trade-offs of sorting dictionaries in Python, you’ll be able to apply these concepts to your own code and make informed decisions about choosing the right data structure and sorting method for your specific use case.

Remove ads

Liked it | Disliked it