Sort a dictionary by key in Python

By James L.

In Python 3.7 and later, dictionaries are ordered by default, preserving the order in which key-value pairs are inserted. When iterating over a dictionary, the items are returned in the order they were inserted. This order-preserving behavior enables sorting dictionaries in Python.

In this blog post, I will guide you through different approaches to sorting a dictionary by key in Python. We will cover the following topics:

Sort a dictionary by key using sorted() function

You can use the built-in sorted() function to sort a dictionary by its keys in Python.

Here’s an example:

my_dict = {"Bob": 20, "Alice": 90, "John": 50}

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

print(sorted_dict)

Now, let’s understand how the code works:

  • my_dict.items() returns a view object containing the key-value pairs of the dictionary as tuples in a list. In our case, it would be [('Bob', 20), ('Alice', 90), ('John', 50)].
  • sorted() function sorts the list of tuples in ascending order based on the keys.
  • sorted() function always returns a list (in our case, the sorted list of tuples). The resulting sorted list would be [('Alice', 90), ('Bob', 20), ('John', 50)].
  • dict(...) takes an iterable (in our case, the sorted list of tuples) and creates a new dictionary from it. The new dictionary is assigned to the variable sorted_dict.

So, in summary, the above code takes a dictionary, sorts its key-value pairs based on the keys in alphabetical order, and creates a new dictionary with the sorted key-value pairs. The original dictionary (my_dict) remains unchanged.

Also note that in the above example, we pass my_dict.items() instead of just my_dict to the sorted() function. Passing my_dict alone to sorted() would return a sorted list of the dictionary’s keys, rather than the desired output of sorted key-value pairs.

Here’s what I mean:

my_dict = {"Bob": 20, "Alice": 90, "John": 50}

sorted_dict = sorted(my_dict)

print(sorted_dict)  # Output: ['Alice', 'Bob', 'John']

Alternatively, you can also pass the lambda function as the key parameter to the sorted() function. Here’s the code:

sorted_dict = dict(sorted(my_dict.items(), key=lambda x: x[0]))

key=lambda x: x[0] is a lambda function that takes each tuple x and returns the first element x[0], which is the key (value is x[1]).

sorted() function will sort the list of tuples based on the keys returned by the lambda function. The resulting sorted list would be [('Alice', 90), ('Bob', 20), ('John', 50)].

Sort a dictionary by key in descending order

You can sort a dictionary by key in descending order by setting the reverse parameter of the sorted() function to True.

Here’s an example:

my_dict = {"Bob": 20, "Alice": 90, "John": 50}

sorted_dict = dict(sorted(my_dict.items(), key=lambda x: x[0], reverse=True))

print(sorted_dict)  # Output: {'John': 50, 'Bob': 20, 'Alice': 90}

Case-insensitive sorting of a dictionary by key

Sorting a dictionary by string keys requires special consideration, as words starting with uppercase letters take precedence over lowercase.

To perform case-insensitive sorting of a dictionary by keys whose keys are strings, you can use the sorted() function along with a custom key function that converts the strings to lowercase before sorting. This way, the sorting will be based on the lowercase representation of the strings, effectively making it case-insensitive.

Here are three different approaches to convert strings to lowercase:

Using lower():

This method converts strings to lowercase before sorting, but may not handle all Unicode characters and locale-specific case representations.

Here’s an example:

my_dict = {"Bob": 20, "alice": 90, "john": 50}

sorted_dict = dict(sorted(my_dict.items(), key=lambda x: x[0].lower()))

print(sorted_dict)  # Output: {'alice': 90, 'Bob': 20, 'john': 50}

Using casefold():

This method is more robust than lower() for case-insensitive sorting, as it provides better support for Unicode characters and internationalization.

Here’s an example:

my_dict = {"Tim": 40, "Sunny": 30, "ßtefan": 50, "alice": 90}

sorted_dict = dict(sorted(my_dict.items(), key=lambda x: x[0].casefold()))

print(sorted_dict)

In this example, I’ve included the name “ßtefan” as the key of the dictionary. This is a German name starting with the letter “ß”.

When using lower(), the “ß” character is retained, resulting in “ßtefan”.

However, when using casefold(), the “ß” character is correctly case-folded to its lowercase equivalent “ss”, resulting in “sstefan”, which ensures proper sorting according to the linguistic rules.

Using locale.strxfrm():

This method uses the current locale for locale-aware case-insensitive sorting, making it suitable for culturally-specific string sorting.

Here’s an example:

import locale

my_dict = {"Tim": 40, "Sunny": 30, "Stéfan": 50, "Álice": 90}

# Set locale to the user's default
locale.setlocale(locale.LC_ALL, '')

sorted_dict = dict(sorted(my_dict.items(), key=lambda x: locale.strxfrm(x[0])))

print(sorted_dict)
# Output: {'Álice': 90, 'Stéfan': 50, 'Sunny': 30, 'Tim': 40}

Note: Output may vary based on your system locale.

Error handling

In Python, dictionary keys can be of various immutable data types such as strings, numbers (integers and floats), tuples, booleans, and frozen sets.

If your dictionary contains keys of different data types, attempting to sort the dictionary items by keys will raise a TypeError.

Before sorting, you can either check the data types and convert them if necessary, or simply show an error message to the user.

Here’s an example that displays an error message if you try to sort a dictionary by keys of different data types:

my_dict = {"a": 5, 4: 10, "b": 15}

try:
    sorted_dict = sorted(my_dict.items())
    print(sorted_dict)
except TypeError:
    print("TypeError: Dictionary contains unsortable keys")

# Output: TypeError: Dictionary contains unsortable keys

In this example, the keys of the dictionary my_dict are a mix of strings ("a" and "b") and an integer (4). The sorted() function cannot sort a dictionary based on these keys because it doesn’t know how to compare strings and integers. So a TypeError exception is raised and the code inside the except block is executed. In our case, it prints the message TypeError: Dictionary contains unsortable keys.

Conclusion

In this blog post, we covered several approaches to sorting a dictionary by its keys in Python. We started with the built-in sorted() function along with the dict() constructor. We then explored how to sort dictionaries in descending order by setting the reverse parameter of the sorted() function to True.

Additionally, we discussed case-insensitive sorting of dictionaries with string keys using different approaches, such as lower(), casefold(), and locale.strxfrm(). The choice among these methods depends on your specific requirements.

However, here’s the summary:

  • Use lower() if:
    • You are confident your text is purely ASCII without special characters or accented letters.
    • You prioritize performance and simplicity.
  • Use casefold() if:
    • You are working with Unicode text that might contain special characters or accented letters.
    • You want to ensure consistent results across different languages and locales.
    • It is less efficient than lower() due to the additional processing required to handle more complex cases.
  • Use locale.strxfrm if:
    • You need language-specific sorting based on cultural conventions.
    • The result may vary across different systems due to differences in locale settings.
    • It might be overkill for basic case-insensitive sorting.

Lastly, we addressed error handling when sorting dictionaries with keys of different data types using the try-except block.

By understanding these concepts and techniques, you can effectively sort dictionaries by keys in Python.