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

Я получил список словарей и хочу, чтобы каждый элемент сортировался по определенным значениям свойств.

Примите во внимание массив ниже,

[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

При сортировке по name должно

[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
1386
задан masi 16 сент. '08 в 17:27
источник поделиться
17 ответов

Он может выглядеть более чистым, используя ключ вместо cmp:

newlist = sorted(list_to_be_sorted, key=lambda k: k['name']) 

или как J.F.Sebastian и другие предположили,

from operator import itemgetter
newlist = sorted(list_to_be_sorted, key=itemgetter('name')) 

Для полноты (как указано в комментариях fitzgeraldsteele), добавьте reverse=True для сортировки нисходящего

newlist = sorted(l, key=itemgetter('name'), reverse=True)
1862
ответ дан Mario F 16 сент. '08 в 17:39
источник поделиться
import operator

Чтобы отсортировать список словарей по ключу = 'name':

list_of_dicts.sort(key=operator.itemgetter('name'))

Чтобы отсортировать список словарей по ключу = "возраст":

list_of_dicts.sort(key=operator.itemgetter('age'))
113
ответ дан vemury 16 сент. '08 в 18:18
источник поделиться

Если вы хотите отсортировать список по нескольким клавишам, вы можете сделать следующее:

my_list = [{'name':'Homer', 'age':39}, {'name':'Milhouse', 'age':10}, {'name':'Bart', 'age':10} ]
sortedlist = sorted(my_list , key=lambda elem: "%02d %s" % (elem['age'], elem['name']))

Он довольно хакерский, поскольку он полагается на преобразование значений в одно строковое представление для сравнения, но он работает как ожидалось для чисел, включая отрицательные (хотя вам нужно будет соответствующим образом отформатировать строку с нулевыми прокладками, если вы используете номера)

41
ответ дан Dologan 18 мая '10 в 18:28
источник поделиться
my_list = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

my_list.sort(lambda x,y : cmp(x['name'], y['name']))

my_list теперь будет тем, что вы хотите.

(3 года спустя) Отредактировано для добавления:

Новый аргумент key более эффективен и опрятен. Теперь лучший ответ выглядит следующим образом:

my_list = sorted(my_list, key=lambda k: k['name'])

... lambda is, IMO, легче понять, чем operator.itemgetter, но YMMV.

29
ответ дан pjz 16 сент. '08 в 17:39
источник поделиться
import operator
a_list_of_dicts.sort(key=operator.itemgetter('name'))

"ключ" используется для сортировки по произвольному значению, а "itemgetter" устанавливает это значение для атрибута "имя" каждого элемента.

22
ответ дан efotinis 16 сент. '08 в 17:43
источник поделиться

Думаю, вы имели в виду:

[{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

Это будет отсортировано следующим образом:

sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))
16
ответ дан Bartosz Radaczyński 16 сент. '08 в 17:36
источник поделиться

Используя преобразование Шварца из Perl,

py = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

делать

sort_on = "name"
decorated = [(dict_[sort_on], dict_) for dict_ in py]
decorated.sort()
result = [dict_ for (key, dict_) in decorated]

дает

>>> result
[{'age': 10, 'name': 'Bart'}, {'age': 39, 'name': 'Homer'}]

Подробнее о Perl-преобразование Шварца

В информатике преобразование Шварца представляет собой программирование на Perl идиома, используемая для повышения эффективности сортировки списка предметов. Эта идиома подходит для сортировки на основе сравнения, когда упорядочение фактически основанный на упорядочении определенного свойства (ключа) элементов, где вычисление этого свойства является интенсивной операцией, которая должно выполняться минимально. Шварццы Transform отличается тем, что он не использует именованные временные массивы.

14
ответ дан octoback 27 мая '13 в 14:21
источник поделиться

Вы можете использовать пользовательскую функцию сравнения или вы можете передать функцию, которая вычисляет собственный ключ сортировки. Это обычно более эффективно, поскольку ключ вычисляется только один раз за элемент, тогда как функция сравнения будет вызываться еще много раз.

Вы можете сделать это следующим образом:

def mykey(adict): return adict['name']
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=mykey)

Но стандартная библиотека содержит общую процедуру для получения элементов произвольных объектов: itemgetter. Поэтому попробуйте это:

from operator import itemgetter
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=itemgetter('name'))
13
ответ дан Owen 16 сент. '08 в 17:52
источник поделиться

Вы должны реализовать свою собственную функцию сравнения, которая будет сравнивать словари по значениям имен ключей. См. Сортировка Mini-HOW TO из PythonInfo Wiki

12
ответ дан Matej 16 сент. '08 в 17:31
источник поделиться
a = [{'name':'Homer', 'age':39}, ...]

# This changes the list a
a.sort(key=lambda k : k['name'])

# This returns a new list (a is not modified)
sorted(a, key=lambda k : k['name']) 
11
ответ дан forzagreen 17 марта '17 в 13:29
источник поделиться

Я пробовал что-то вроде этого:

my_list.sort(key=lambda x: x['name'])

Он работал и для целых чисел.

7
ответ дан Sandip Agarwal 14 сент. '12 в 11:05
источник поделиться

Вот альтернативное общее решение - оно сортирует элементы 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)
sorted(A, key=sort_key_func)
6
ответ дан vvladymyrov 22 янв. '15 в 20:21
источник поделиться

Использование пакета pandas - это еще один метод, хотя время выполнения в больших масштабах намного медленнее, чем более традиционные методы, предлагаемые другими:

import pandas as pd

listOfDicts = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]
df = pd.DataFrame(listOfDicts)
df = df.sort_values('name')
sorted_listOfDicts = df.T.to_dict().values()

Ниже приведены некоторые контрольные значения для крошечного списка и большого (100k +) списка dicts:

setup_large = "listOfDicts = [];\
[listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10})) for _ in range(50000)];\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"

setup_small = "listOfDicts = [];\
listOfDicts.extend(({'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}));\
from operator import itemgetter;import pandas as pd;\
df = pd.DataFrame(listOfDicts);"

method1 = "newlist = sorted(listOfDicts, key=lambda k: k['name'])"
method2 = "newlist = sorted(listOfDicts, key=itemgetter('name')) "
method3 = "df = df.sort_values('name');\
sorted_listOfDicts = df.T.to_dict().values()"

import timeit
t = timeit.Timer(method1, setup_small)
print('Small Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_small)
print('Small Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_small)
print('Small Method Pandas: ' + str(t.timeit(100)))

t = timeit.Timer(method1, setup_large)
print('Large Method LC: ' + str(t.timeit(100)))
t = timeit.Timer(method2, setup_large)
print('Large Method LC2: ' + str(t.timeit(100)))
t = timeit.Timer(method3, setup_large)
print('Large Method Pandas: ' + str(t.timeit(1)))

#Small Method LC: 0.000163078308105
#Small Method LC2: 0.000134944915771
#Small Method Pandas: 0.0712950229645
#Large Method LC: 0.0321750640869
#Large Method LC2: 0.0206089019775
#Large Method Pandas: 5.81405615807
5
ответ дан abby sobh 02 сент. '16 в 0:21
источник поделиться

Когда-то нам нужно использовать lower(), например

lists = [{'name':'Homer', 'age':39},
  {'name':'Bart', 'age':10},
  {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'])
print(lists)
# [{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}, {'name':'abby', 'age':9}]

lists = sorted(lists, key=lambda k: k['name'].lower())
print(lists)
# [ {'name':'abby', 'age':9}, {'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
4
ответ дан uingtea 14 июля '17 в 6:21
источник поделиться

Позволяет сказать, что я имею словарь D с элементами ниже. Для сортировки просто используйте аргумент ключа в сортировке для передачи пользовательской функции, как показано ниже

D = {'eggs': 3, 'ham': 1, 'spam': 2}

def get_count(tuple):
    return tuple[1]

sorted(D.items(), key = get_count, reverse=True)
or
sorted(D.items(), key = lambda x: x[1], reverse=True)  avoiding get_count function call

https://wiki.python.org/moin/HowTo/Sorting/#Key_Functions

3
ответ дан Shank_Transformer 16 апр. '14 в 10:18
источник поделиться

Вот мой ответ на соответствующий вопрос по сортировке по нескольким столбцам. Он также работает для вырожденного случая, когда число столбцов равно одному.

2
ответ дан hughdbrown 17 июля '09 в 21:22
источник поделиться

Если вам не нужен оригинальный list из dictionaries, вы можете изменить его на месте с помощью метода sort(), используя специальную ключевую функцию.

Ключевая функция:

def get_name(d):
    """ Return the value of a key in a dictionary. """

    return d["name"]

list для сортировки:

data_one = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]

Сортировка на месте:

data_one.sort(key=get_name)

Если вам нужен оригинальный list, вызовите функцию sorted(), передав ей list и ключевую функцию, затем присвойте возвращаемому отсортированному list новую переменную:

data_two = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age': 10}]
new_data = sorted(data_two, key=get_name)

Печать data_one и new_data.

>>> print(data_one)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
>>> print(new_data)
[{'name': 'Bart', 'age': 10}, {'name': 'Homer', 'age': 39}]
0
ответ дан srig 19 дек. '17 в 20:31
источник поделиться

Другие вопросы по меткам