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

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

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

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

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

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

Ответ 1

Он может выглядеть более чистым, используя ключ вместо 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)

Ответ 2

import operator

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

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

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

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

Ответ 3

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.

Ответ 4

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

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

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

Ответ 5

import operator
a_list_of_dicts.sort(key=operator.itemgetter('name'))

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

Ответ 6

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

Ответ 7

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

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

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

sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))

Ответ 8

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

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

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'))

Ответ 9

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

Ответ 10

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

Ответ 11

Вот альтернативное общее решение - оно сортирует элементы 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)

Ответ 12

Когда-то нам нужно использовать 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}]

Ответ 13

Использование пакета 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

Ответ 14

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

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

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

Ответ 15

Допустим, у меня есть словарь 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

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

Ответ 16

Если вам не нужен оригинальный 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}]

Ответ 18

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

Первый вариант

sorted_list = sorted(list_to_sort, key= lambda x: x['name'])
# returns list of values

Второй вариант

list_to_sort.sort(key=operator.itemgetter('name'))
#edits the list, does not return a new list

Быстрое сравнение времени исполнения

# First option
python3.6 -m timeit -s "list_to_sort = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}, {'name':'Faaa', 'age':57}, {'name':'Errr', 'age':20}]" -s "sorted_l=[]" "sorted_l = sorted(list_to_sort, key=lambda e: e['name'])"

1000000 loops, best of 3: 0.736 usec per loop

# Second option 
python3.6 -m timeit -s "list_to_sort = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}, {'name':'Faaa', 'age':57}, {'name':'Errr', 'age':20}]" -s "sorted_l=[]" -s "import operator" "list_to_sort.sort(key=operator.itemgetter('name'))"

1000000 loops, best of 3: 0.438 usec per loop

Ответ 19

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

sorted_dct = sorted(dct_name.items(), key = lambda x : x[1])