Effortlessly Sorting Dict in Python
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, we will go over everything you need to know about sorting dictionaries in Python.
In this tutorial, you will:
- 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, we will also use the timeit
module to time our code and get tangible results for comparing the different methods of sorting key-value data. We will also consider whether a sorted dictionary is really the best option, as it’s not a particularly common pattern.
To get the most out of this tutorial, you should have knowledge 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.
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. Since Python 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 had to use the collections.OrderedDict
class from the collections
module.
Now, let’s start exploring how to sort dictionaries in Python.
Understanding What Sorting A Dictionary Really Means
Before diving into different methods of sorting dictionaries, let’s clarify what “sorting a dictionary” actually means. In Python, dictionaries are inherently unordered collections of key-value pairs. Sorting a dictionary means ordering its key-value pairs based on certain criteria.
When sorting a dictionary, you have the option to sort by keys, values, or even a nested attribute. You can also choose whether to sort in ascending or descending order based on those criteria.
Now, let’s proceed to the next section and see how to sort dictionaries in Python.
Sorting Dictionaries in Python
Using the sorted()
Function
The simplest way to sort a dictionary is by using the sorted()
function. The sorted()
function takes an iterable, such as a dictionary, and returns a new sorted list of its elements.
For dictionaries, the sorted()
function sorts the dictionary keys by default. Let’s see an example:
Output:
As you can see, the sorted()
function returns a new list containing the keys of the dictionary in sorted order.
If you want to sort the dictionary by its values rather than keys, you can use the items()
method to get a dictionary view and then pass that view to the sorted()
function. Let’s see an example:
Output:
In this example, we used the items()
method to get a dictionary view of key-value pairs. We then passed this view to the sorted()
function with a lambda function as the key
parameter. The lambda function extracts the second element of each pair (the values) and uses them as the sort key.
Getting Keys, Values, or Both From a Dictionary
In addition to the items()
method, dictionaries provide other useful methods for accessing their keys, values, or both.
- keys(): This method returns a dictionary view of just the keys.
- values(): This method returns a dictionary view of just the values.
Let’s see an example that demonstrates these methods:
Output:
These methods return dictionary views, which are dynamic and reflect any changes made to the original dictionary. You can pass these views to the sorted()
function, just like we did in the previous example.
Understanding How Python Sorts Tuples
In the previous example, we sorted the dictionary by its values using the sorted()
function and a lambda function as the key
parameter. But how does Python know how to sort tuples?
When sorting a sequence of tuples, Python compares the elements of each tuple in order, starting with the first element. If the first elements are equal, it compares the second elements, and so on.
For example, let’s sort a list of tuples based on the second element of each tuple:
Output:
In this example, the lambda function extracts the second element of each tuple and uses it as the sort key. Python compares the second elements and orders the list accordingly.
Now that we understand how Python sorts tuples, let’s see how we can use this knowledge to sort dictionaries.
Using the key
Parameter and Lambda Functions
The sorted()
function accepts a key
parameter, which allows you to specify a function that extracts a comparison key from each element. In the previous example, we used a lambda function as the key
parameter to extract the second element of each tuple.
Similarly, we can use a lambda function to specify a sort key for dictionaries. The lambda function takes a dictionary element as input and returns the desired sort key.
Let’s see an example where we sort a dictionary by the length of its keys:
Output:
In this example, the lambda function extracts the keys of each pair and uses the len()
function to get their lengths. Python then compares the lengths and orders the list accordingly.
You can use lambda functions to sort dictionaries based on various criteria, such as values, keys, or nested attributes. It provides flexibility and allows you to define custom sorting logic.
Selecting a Nested Value With a Sort Key
In some cases, you may want to sort a dictionary based on a nested attribute of its values. To achieve this, you need to specify a sort key that selects the desired attribute from the nested value.
Let’s see an example where we sort a dictionary based on the ‘price’ attribute of its values, where the values themselves are dictionaries:
Output:
In this example, the lambda function selects the ‘price’ attribute from the nested dictionary using the key x[1]['price']
. Python then compares the prices and orders the list accordingly.
Converting Back to a Dictionary
After sorting a dictionary, you may want to convert it back to a dictionary format. You can use dictionary comprehensions or the dict()
constructor to achieve this.
Let’s see an example using dictionary comprehensions:
Output:
In this example, we used a dictionary comprehension to create a new dictionary with the same key-value pairs but sorted by values. We passed the sorted dictionary view to the sorted()
function and used a lambda function as the key
parameter to sort by values.
You can achieve the same result by using the dict()
constructor with the sorted dictionary view:
Output:
Both methods will give you the sorted dictionary back.
Considering Strategic and Performance Issues
When sorting dictionaries, it’s important to consider both strategic and performance issues. Sorting dictionaries can have implications on the read and write operations, as well as memory usage.
Using Special Getter Functions to Increase Performance and Readability
Sorting dictionaries using the key
parameter and lambda functions can be powerful, but it can also be slow for large datasets. In such cases, you can use special getter functions to increase performance while maintaining code readability.
Python’s operator
module provides functions that abstract the retrieval of nested attributes, making your code more readable and potentially faster.
Let’s see an example of how to use the operator.itemgetter()
function to sort a dictionary based on a nested attribute:
Output:
In this example, we used the operator.itemgetter()
function as the key
parameter. It takes a sequence of keys as arguments and returns a callable that retrieves the corresponding nested attributes from the item being sorted.
Using operator.itemgetter()
can improve performance compared to lambda functions, especially for large datasets.
Measuring Performance When Using itemgetter()
To measure the performance improvement when using operator.itemgetter()
, you can use the timeit
module.
Here’s an example of how to measure the performance of sorting a large dictionary using itemgetter()
:
Output:
In this example, we created a large dictionary with 100,000 key-value pairs. We defined two functions, sort_with_itemgetter()
and sort_with_lambda()
, to sort the dictionary using operator.itemgetter()
and a lambda function respectively. We measured the execution time of each function using timeit.timeit()
with 100 repetitions.
The results show a significant improvement in performance when using operator.itemgetter()
compared to lambda functions.
Judging Whether You Want to Use a Sorted Dictionary
Although sorting dictionaries can be useful in certain scenarios, it’s important to consider whether a sorted dictionary is really necessary for your use case. Sorting a dictionary requires additional computational resources and can impact the performance of read and write operations.
If you need to access items from a dictionary in a specific order, using a different data structure, such as collections.OrderedDict
or a list of tuples, might be a better choice.
Comparing the Performance of Different Data Structures
To compare the performance of different data structures for storing key-value data, you can use the timeit
module.
Here’s an example of how to measure the performance of accessing items from a dictionary, collections.OrderedDict
, and a list of tuples:
Output:
In this example, we defined three access functions to retrieve the value associated with the key ‘50000’ from a dictionary, collections.OrderedDict
, and a list of tuples respectively. We measured the execution time of each function using timeit.timeit()
with 100,000 repetitions.
The results show that accessing items from a dictionary is the fastest, followed by collections.OrderedDict
, and finally by a list of tuples.
Comparing the Performance of Sorting
To compare the performance of different sorting methods, you can use the timeit
module.
Here’s an example of how to measure the performance of sorting a large dictionary using different methods:
Output:
In this example, we created a large dictionary with 100,000 key-value pairs. We defined three sorting functions using different methods: sorted()
with a lambda function, sorted()
with operator.itemgetter()
, and a dictionary comprehension with sorting. We measured the execution time of each function using timeit.timeit()
with 10 repetitions.
The results show that sorting using the sorted()
function with a lambda function is the fastest, followed by sorting using operator.itemgetter()
, and finally by sorting with a dictionary comprehension.
Comparing the Performance of Lookups
To compare the performance of lookups in different data structures, you can use the timeit
module.
Here’s an example of how to measure the performance of lookups in a dictionary, collections.OrderedDict
, and a list of tuples:
Output:
In this example, we defined three lookup functions to retrieve the value associated with the key ‘50000’ from a dictionary, collections.OrderedDict
, and a list of tuples respectively. We measured the execution time of each function using timeit.timeit()
with 100,000 repetitions.
The results show that lookups in dictionaries and collections.OrderedDict
have similar performance, and both are significantly faster than lookups in lists of tuples.
Conclusion
In this tutorial, we explored different methods of sorting dictionaries in Python. We started by using the sorted()
function and saw how it can sort dictionaries by keys or values. We then learned how to specify a sort key using lambda functions and the key
parameter.
We also discovered how to select a nested value with a sort key and explored different techniques for converting a sorted dictionary back to its original format using dictionary comprehensions and the dict()
constructor.
Along the way, we considered strategic and performance issues when sorting dictionaries, such as using special getter functions to increase performance and readability, judging whether a sorted dictionary is really necessary, and comparing the performance of different data structures, sorting methods, and lookups.
With the knowledge gained from this tutorial, you should be able to effectively sort dictionaries in Python and make informed decisions based on your specific use case.