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

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

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

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

Когда отсортировано по name, должно стать

[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
+1616
16 сент. '08 в 14:27
источник поделиться
18 ответов

Он может выглядеть более чистым, используя ключ вместо 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)
+2142
16 сент. '08 в 14:39
источник

Связанные вопросы


Похожие вопросы

import operator

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

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

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

list_of_dicts.sort(key=operator.itemgetter('age'))
+129
16 сент. '08 в 15: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']))

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

+42
18 мая '10 в 15: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.

+42
16 сент. '08 в 14:39
источник
import operator
a_list_of_dicts.sort(key=operator.itemgetter('name'))

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

+26
16 сент. '08 в 14:43
источник
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']) 
+19
17 мар. '17 в 10:29
источник

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

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

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

sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))
+18
16 сент. '08 в 14:36
источник

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

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

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'))
+16
16 сент. '08 в 14:52
источник

Используя преобразование Шварца из 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 отличается тем, что он не использует именованные временные массивы.

+16
27 мая '13 в 11:21
источник

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

+15
16 сент. '08 в 14:31
источник

Когда-то нам нужно использовать 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}]
+10
14 июл. '17 в 3:21
источник

Вот альтернативное общее решение - оно сортирует элементы 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)
+10
22 янв. '15 в 17: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
+8
01 сент. '16 в 21:21
источник

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

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

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

+7
14 сент. '12 в 8:05
источник

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

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

Проверьте это.

+4
16 апр. '14 в 7:18
источник

Если вам не нужен оригинальный 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}]
+3
19 дек. '17 в 17:31
источник

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

+2
17 июл. '09 в 18:22
источник

Вы можете использовать следующий код

sorted_dct = sorted(dct_name.items(), key = lambda x : x[1])
-1
30 нояб. '18 в 9:40
источник

Посмотрите другие вопросы по меткам или Задайте вопрос