Python: How to sort a list of dictionaries by several values?

PythonListSorting

Python Problem Overview


I want to sort a list at first by a value and then by a second value. Is there an easy way to do this? Here is a small example:

A = [{'name':'john','age':45},     {'name':'andi','age':23},     {'name':'john','age':22},     {'name':'paul','age':35},     {'name':'john','age':21}]

This command is for sorting this list by 'name':

sorted(A, key = lambda user: user['name'])

But how I can sort this list by a second value? Like 'age' in this example.

I want a sorting like this (first sort by 'name' and then sort by 'age'):

andi - 23
john - 21
john - 22
john - 45
paul - 35

Thanks!

Python Solutions


Solution 1 - Python

>>> A = [{'name':'john','age':45},     {'name':'andi','age':23},     {'name':'john','age':22},     {'name':'paul','age':35},     {'name':'john','age':21}]
>>> sorted(A, key = lambda user: (user['name'], user['age']))
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}]

This sorts by a tuple of the two attributes, the following is equivalent and much faster/cleaner:

>>> from operator import itemgetter
>>> sorted(A, key=itemgetter('name', 'age'))
[{'age': 23, 'name': 'andi'}, {'age': 21, 'name': 'john'}, {'age': 22, 'name': 'john'}, {'age': 45, 'name': 'john'}, {'age': 35, 'name': 'paul'}]

From the comments: @Bakuriu

>I bet there is not a big difference between the two, but itemgetter avoids a bit of overhead because it extracts the keys and make the tuple during a single opcode(CALL_FUNCTION), while calling the lambda will have to call the function, load the various constants(which are other bytecodes) finally call the subscript (BINARY_SUBSCR), build the tuple and return it... that's a lot more work for the interpreter.

To summarize: itemgetter keeps the execution fully on the C level, so it's as fast as possible.

Solution 2 - Python

from operator import itemgetter

sorted(your_list, key=itemgetter('name', 'age'))

Solution 3 - Python

Here is the alternative general solution - it sorts elements of dict by keys and values. The advantage of it - no need to specify keys, and it would still work if some keys are missing in some of dictionaries.

def sort_key_func(item):
    """ helper function used to sort list of dicts

    :param item: dict
    :return: sorted list of tuples (k, v)
    """
    pairs = []
    for k, v in item.items():
        pairs.append((k, v))
    return sorted(pairs)

Attributions

All content for this solution is sourced from the original question on Stackoverflow.

The content on this page is licensed under the Attribution-ShareAlike 4.0 International (CC BY-SA 4.0) license.

Content TypeOriginal AuthorOriginal Content on Stackoverflow
QuestionJokoView Question on Stackoverflow
Solution 1 - PythonjamylakView Answer on Stackoverflow
Solution 2 - PythonJon ClementsView Answer on Stackoverflow
Solution 3 - PythonvvladymyrovView Answer on Stackoverflow