Python: как отсортировать список словарей по нескольким значениям?

Я хочу сначала отсортировать список по значению, а затем по второму значению. Есть простой способ сделать это? Вот небольшой пример:

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

Эта команда предназначена для сортировки этого списка с помощью 'name':

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

Но как я могу сортировать этот список по второму значению? Например, 'age' в этом примере.

Мне нужна сортировка вроде этого (сначала сортировка 'name', а затем сортировка по 'age'):

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

Спасибо!

Ответ 1

>>> 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'}]

Это сортирует по кортежу из двух атрибутов, следующее эквивалентно и намного быстрее/чище:

>>> 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'}]

Из комментариев: @Bakuriu

Я уверен, что между ними нет большой разницы, но itemgetter избегает бит служебных данных, потому что он извлекает ключи и делает tuple в течение одного кода операции (CALL_FUNCTION), вызывая lambda нужно будет вызвать функцию, загрузить различные константы (которые являются другими байткодами), наконец, вызвать индекс (BINARY_SUBSCR), построить tuple и вернуть его... что гораздо больше работает для интерпретатора.

Подводя итог: itemgetter полностью выполняет выполнение на уровне C, поэтому он как можно быстрее.

Ответ 2

from operator import itemgetter

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

Ответ 3

Вот альтернативное общее решение - оно сортирует элементы dict по ключам и значениям. Преимущество этого - нет необходимости указывать ключи, и он все равно будет работать, если некоторые ключи отсутствуют в некоторых словарях.

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)