Sort a list of dictionaries by value in Python

By James L.

In Python, sorting a list of dictionaries by a specific key value is straightforward. Python offers two methods for achieving this: the sorted() function and the sort() method.

We will discuss the following topics in this blog post:

# Sort a list of dictionaries using sorted() function

To sort a list of dictionaries using the sorted() function, you can specify the key parameter to indicate which key’s value to use for sorting.

Here is an example:

my_list_of_dicts = [{'name': 'Alice', 'age': 30}, {
    'name': 'Bob', 'age': 25}, {'name': 'Charlie', 'age': 35}]

sorted_list = sorted(my_list_of_dicts, key=lambda x: x['age'])

print(sorted_list)

# Output: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie', 'age': 35}]

In this example, the list of dictionaries is sorted based on the 'age' key in ascending order.

(a) Sort a list of dictionaries in descending order

To sort a list of dictionaries in descending order, you can set the reverse parameter of the sorted() function to True.

Here’s an example:

my_list_of_dicts = [{'name': 'Alice', 'age': 30}, {
    'name': 'Bob', 'age': 25}, {'name': 'Charlie', 'age': 35}]

sorted_list = sorted(my_list_of_dicts, key=lambda x: x['age'], reverse=True)

print(sorted_list)

# Output: [{'name': 'Charlie', 'age': 35}, {'name': 'Alice', 'age': 30}, {'name': 'Bob', 'age': 25}]

In this example, the list of dictionaries is sorted based on the value of 'age' key in descending order. The reverse=True parameter ensures that the sorting is done in reverse order.

(b) Sort a list of dictionaries based on a custom sorting function

You can also define your own custom sorting function to decide the sorting criteria and pass it as the key parameter to the sorted() function.

Here’s an example that sorts a list of dictionaries based on the length of the name value:

# Define a custom function to determine the sorting key
def my_func(dict):
    # Returns the length of the 'name' value in dictionary
    return len(dict['name'])


my_list_of_dicts = [{'name': 'Alice', 'age': 30}, {
    'name': 'Bob', 'age': 25}, {'name': 'Charlie', 'age': 35}]

# Sort the list of dictionaries using the custom function as the sorting key
sorted_list = sorted(my_list_of_dicts, key=my_func)

print(sorted_list)

# Output: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie', 'age': 35}]

(c) Sort a list of dictionaries based on multiple values

When working with data stored in dictionaries, you often need to sort them based on multiple criteria. For example, imagine you have a list of customer records with information like name, age, and city. You might want to sort them by age first, then by name within each age group.

To achieve this, you can pass a tuple of key functions to the key parameter of the sorted() function.

Here’s an example:

people_data = [
    {"name": "Alice", "age": 30, "city": "New York"},
    {"name": "Bob", "age": 25, "city": "Los Angeles"},
    {"name": "Charlie", "age": 35, "city": "Chicago"},
    {"name": "David", "age": 25, "city": "Detroit"}
]

sorted_data = sorted(people_data, key=lambda item: (item["age"], item["name"]))

print(sorted_data)
# Output: [{'name': 'Bob', 'age': 25, 'city': 'Los Angeles'}, {'name': 'David', 'age': 25, 'city': 'Detroit'}, {'name': 'Alice', 'age': 30, 'city': 'New York'}, {'name': 'Charlie', 'age': 35, 'city': 'Chicago'}]

In this example, the key parameter of the sorted() function is set to a lambda function. This lambda function takes each dictionary item from people_data and returns a tuple (item["age"], item["name"]). This means the sorting is first done by age in ascending order and then by name in alphabetical order.

As you can see, the list is sorted first by age (Bob and David are both 25 years old), and then alphabetically by name within the same age group.

(d) Case-insensitive sorting list of dictionaries

Sorting a list of dictionaries based on string values requires special consideration, especially while doing case-insensitive sorting. Python provides built-in options to handle these scenarios.

Here’s an example:

fruits = [
    {"name": "apple", "price": 20},
    {"name": "Orange", "price": 50},
    {"name": "Banana", "price": 10},
    {"name": "grape", "price": 30}
]

# Sorting the list of dictionaries of fruits alphabetically by name (case-insensitive)
sorted_fruits = sorted(fruits, key=lambda fruit: (fruit["name"].casefold()))

print(sorted_fruits)
# Output: [{'name': 'apple', 'price': 20}, {'name': 'Banana', 'price': 10}, {'name': 'grape', 'price': 30}, {'name': 'Orange', 'price': 50}]

Using casefold() ensures that the fruits list is sorted alphabetically without considering the case. This Python string method converts all Unicode characters to lowercase, making it more comprehensive than lower() for case-insensitive sorting.

(e) Sorting list of dictionaries using itemgetter()

The itemgetter() is a function from the operator module in Python that allows you to access specific elements within a sequence (like list, tuple, or dictionary) based on their index.

You can use this function to sort a list of dictionaries. Here’s an example:

from operator import itemgetter

fruits = [
    {"name": "apple", "price": 20},
    {"name": "orange", "price": 50},
    {"name": "banana", "price": 10},
    {"name": "grape", "price": 30}
]

# Sorting the list of dictionaries of fruits by price in ascending order
sorted_fruits = sorted(fruits, key=itemgetter("price"))

print(sorted_fruits)
# Output: [{'name': 'banana', 'price': 10}, {'name': 'apple', 'price': 20}, {'name': 'grape', 'price': 30}, {'name': 'orange', 'price': 50}]

In this example, itemgetter("price") is used as the key function for sorting, which extracts the value associated with the key "price" from each dictionary in the list for comparison during sorting.

(f) Lambda function vs itemgetter()

Lambda function:

  • They are ideal for complex sorting criteria involving comparisons, calculations, or conditional logic.
  • They are generally slower than itemgetter() for large datasets due to the overhead of function calls.

itemgetter():

  • If your sorting logic is straightforward, itemgetter() is often more readable and efficient.
  • It is faster than the lambda function due to its optimized implementations.

In summary, lambda functions are convenient if your sorting criteria are complex or if you are working with small datasets. However, for larger datasets or when performance is a concern, itemgetter() is generally preferred due to its efficiency.

# Sort list of dictionaries using sort() method

In Python, the sort() method sorts the elements of the list in ascending order by default.

The basic syntax of the sort() method is:

list_name.sort(key=None, reverse=False)
  • list_name: The name of the list you want to sort.
  • key: (Optional) A function to execute to decide the order. Default is None.
  • reverse: (Optional) A boolean. If True the list is sorted in descending order. If False (default), the list is sorted in ascending order.

Alternatively, you can also use the sort() method to sort a list of dictionaries.

Here’s an example:

my_list_of_dicts = [{'name': 'Alice', 'age': 30}, {
    'name': 'Bob', 'age': 25}, {'name': 'Charlie', 'age': 35}]


my_list_of_dicts.sort(key=lambda x: x['age'])


print(my_list_of_dicts)
# Output: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie', 'age': 35}]

You can replace sorted() function with the sort() method for all the examples we talked about earlier in this guide.

# Differences between sorted() function and sort() method

The sorted() function and sort() method are both used for sorting elements in a Python list, but they have some key differences:

  1. Return type:
    • sorted(): Returns a new sorted list from the elements of the iterable (list, tuple, or string). The original iterable remains unchanged.
    • sort(): Sorts the elements of the list in-place and returns None. The original list is modified.
  2. Mutability:
    • sorted(): Creates a new sorted list without modifying the original iterable.
    • sort(): Modifies the original list in-place.
  3. Usage:
    • sorted(): It can be used with any iterable (list, tuple, or string), not just lists. It returns a new sorted list regardless of the type of the original iterable.
    • sort(): Applies only to lists. It is a method of the list class and can only be used with lists.
  4. Performance:
    • The sort() method is generally faster than the sorted() function because it modifies the list in-place, avoiding the overhead of creating a new list.

Here’s a table summarizing the key differences:

Featuresorted()sort()
Return ValueNew sorted listNone
MutabilityNon-mutatingMutates original list
UsageAny iterable objectLists only
PerformanceGenerally slowerGenerally faster

# Error handling

Error handling is an essential aspect of any code, especially when dealing with sorting operations on data structures like lists of dictionaries. Let’s discuss some common error scenarios and how to handle them gracefully:

(a) Missing key

If you try to sort by a key that doesn’t exist in all dictionaries, you will get a KeyError.

To handle this, you can either ensure that all dictionaries have the required key, or use try-except blocks to catch and handle the KeyError.

For example:

my_list_of_dicts = [{'name': 'Alice', 'age': 30}, {
    'name': 'Bob', 'age': 25}, {'name': 'Charlie'}]

try:
    sorted_list = sorted(my_list_of_dicts, key=lambda x: x['age'])
    print(sorted_list)
except KeyError:
    print("One or more dictionaries do not contain the specified key for sorting")

# Output: One or more dictionaries do not contain the specified key for sorting

In this example, the sorted() function attempts to access the 'age' key of one of the dictionaries in the list, it encounters a KeyError because one of the dictionaries does not contain the ‘age’ key. Therefore, the code jumps to the except block and prints the message indicating that one or more dictionaries do not contain the specified key for sorting.

If you want to sort a list of dictionaries regardless of whether the key is missing, you can use the .get(key, default_value) to provide a default value.

Here’s an example:

my_list_of_dicts = [{'name': 'Alice', 'age': 30}, {
    'name': 'Bob', 'age': 25}, {'name': 'Charlie'}]

try:
    sorted_list = sorted(my_list_of_dicts, key=lambda x: x.get('age', 100))
    print(sorted_list)
except KeyError:
    print("One or more dictionaries do not contain the specified key for sorting")

# Output: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie'}]

In this example, the get() method to used to retrieve the value of a key from the dictionary. It takes two arguments: the key whose value you want to retrieve and the optional default value.

Here’s how it works:

  • If the key exists in the dictionary, x.get('age', 100), returns the corresponding value associated with that key.
  • If the key doesn’t exist in the dictionary, x.get('age', 100) returns the default value provided as the second argument, which in this case is 100.

You can use infinity inf to treat missing key values as greater than other values, and similarly, you can use -inf to treat them as smaller.

Here’s an example:

my_list_of_dicts = [{'name': 'Alice', 'age': 30}, {
    'name': 'Bob', 'age': 25}, {'name': 'Charlie'}]

print(sorted(my_list_of_dicts, key=lambda x: x.get('age', float('inf'))))
# Output: [{'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}, {'name': 'Charlie'}]

print(sorted(my_list_of_dicts, key=lambda x: x.get('age', -float('inf'))))
# Output: [{'name': 'Charlie'}, {'name': 'Bob', 'age': 25}, {'name': 'Alice', 'age': 30}]

(b) Uncomparable Types

If you try to compare values of different data types (e.g. string vs. integer), you will get a TypeError.

Check the data types before sorting and convert them if necessary, or raise a specific error message to guide the user.

Here’s an example:

my_list_of_dicts = [{'name': 'Alice', 'age': 40}, {'name': 'Bob', 'age': 25}, {
    'name': 'Charlie', 'age': 'thirty'}]

try:
    sorted_list = sorted(my_list_of_dicts, key=lambda x: x['age'])
    print(sorted_list)
except TypeError:
    print("One or more dictionaries contain inappropriate data for sorting")

In this example, the sorted() function attempts to compare the 'age' values of the dictionaries in the list, it encounters a TypeError due to the fact that one of the dictionaries has a string value ('thirty') for the 'age' key, which cannot be compared with integers. Therefore, the code jumps to the except block and prints the message indicating that inappropriate data for sorting was found.

Conclusion

In this guide, we discussed how to sort a list of dictionaries using the sorted() and sort() methods in Python. We covered various techniques and scenarios, including custom sorting functions, sorting based on multiple values, and error handling strategies for common issues encountered during sorting operations on lists of dictionaries.

Here’s a summary of when to use each:

Use sorted():

  • If you want to keep the original list intact.
  • If you need to create a new sorted list from any iterable object.

Use sort():

  • If you want to modify the original list and don’t need to keep the original order.
  • If performance is a major concern.

Use lambda function:

  • If your sorting criteria are complex or if you are working with small datasets.

Use itemgetter():

  • For large datasets or when performance is a concern.

By understanding these techniques, you can effectively manipulate and sort data stored in dictionaries to meet the requirements of your Python programs.

Happy coding → 3000