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

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

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

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

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

[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
+1687
источник поделиться
19 ответов

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

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

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

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

list_of_dicts.sort(key=operator.itemgetter('age'))
+139
источник
другие ответы

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


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

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.

+49
источник

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

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

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

+46
источник
import operator
a_list_of_dicts.sort(key=operator.itemgetter('name'))

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

+28
источник
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']) 
+21
источник

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

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

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

sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))
+19
источник

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

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

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'))
+17
источник

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

+17
источник

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

+16
источник

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

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

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

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

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

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

+7
источник

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

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

+5
источник

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

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

+2
источник

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

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

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

0
источник

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

sorted_dct = sorted(dct_name.items(), key = lambda x : x[1])
-2
источник

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