Как отсортировать список словарей по значению словаря?
У меня есть список словарей и хочу, чтобы каждый элемент сортировался по определенным значениям свойств.
Примите во внимание массив ниже,
[{'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}]
Ответ 17
Вот мой ответ на соответствующий вопрос по сортировке по нескольким столбцам. Он также работает для вырожденного случая, когда число столбцов равно одному.
Ответ 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])