Jak posortować listę słowników według wartości słownika w Pythonie?

Mam listę słowników i chcę, aby każdy element był posortowany według określonej wartości właściwości.

Weź pod uwagę tablicę poniżej,

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

Po posortowaniu według name, powinno stać się

[{'name':'Bart', 'age':10}, {'name':'Homer', 'age':39}]
Author: masi, 2008-09-16

17 answers

Może wyglądać czystiej używając klucza zamiast cmp:

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

Lub jak zasugerował J. F. Sebastian i inni,

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

Dla kompletności (jak zaznaczono w komentarzach fitzgeraldsteele), dodaj reverse=True do sortowania malejąco

newlist = sorted(l, key=itemgetter('name'), reverse=True)
 1873
Author: Mario F,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-31 19:39:49
import operator

Aby posortować listę słowników według klucza = 'nazwa':

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

Aby posortować listę słowników według klucza = 'wiek':

list_of_dicts.sort(key=operator.itemgetter('age'))
 114
Author: cedbeu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-01 14:42:05

Jeśli chcesz posortować listę według wielu kluczy, możesz wykonać następujące czynności:

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

Jest to raczej hakerskie, ponieważ polega na konwersji wartości na pojedynczą reprezentację ciągu Dla porównania, ale działa zgodnie z oczekiwaniami dla liczb, w tym ujemnych (chociaż będziesz musiał odpowiednio sformatować swój ciąg z zerowymi paddingami, jeśli używasz liczb)

 42
Author: Dologan,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-10 11:31:15
my_list = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

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

my_list Teraz będziesz tym, czego chcesz.

(3 lat później) edytowano aby dodać:

Nowy argument key jest bardziej efektywny i schludniejszy. Teraz lepsza odpowiedź wygląda tak:

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

...lambda jest, IMO, łatwiejsze do zrozumienia niż operator.itemgetter, ale YMMV.

 30
Author: pjz,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-06-06 13:42:15
import operator
a_list_of_dicts.sort(key=operator.itemgetter('name'))

'key' jest używany do sortowania według dowolnej wartości, a 'itemgetter' ustawia tę wartość do atrybutu 'name' każdego elementu.

 23
Author: efotinis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 14:43:51

Chyba miałeś na myśli:

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

To będzie posortowane TAK:

sorted(l,cmp=lambda x,y: cmp(x['name'],y['name']))
 17
Author: Bartosz Radaczyński,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 14:36:54

Używając transformacji Schwartziana z Perla,

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

Do

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

Daje

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

Więcej o Perl Schwartzian transform

W informatyce transformata Schwartziana jest programowaniem Perla idiom używany do poprawy efektywności sortowania listy elementów. To idiom jest odpowiedni do sortowania opartego na porównaniach, gdy kolejność jest faktycznie na podstawie uporządkowania pewnej nieruchomości (klucza) z elementów, gdzie obliczanie, że nieruchomości to intensywna operacja, która należy wykonać minimalną liczbę razy. The Schwartzian Transform jest godny uwagi, ponieważ nie używa nazwanych tablic tymczasowych.

 15
Author: octoback,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-05-27 11:21:03

Możesz użyć niestandardowej funkcji porównawczej lub przekazać funkcję, która oblicza niestandardowy klucz sortowania. Jest to zwykle bardziej wydajne, ponieważ klucz jest obliczany tylko raz na przedmiot, podczas gdy funkcja porównania byłaby wywoływana wiele razy.

Możesz to zrobić w ten sposób:
def mykey(adict): return adict['name']
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=mykey)

Ale biblioteka Standardowa zawiera ogólną procedurę pobierania elementów dowolnych obiektów: itemgetter. Więc spróbuj tego zamiast:

from operator import itemgetter
x = [{'name': 'Homer', 'age': 39}, {'name': 'Bart', 'age':10}]
sorted(x, key=itemgetter('name'))
 14
Author: Owen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 14:52:14

Musisz zaimplementować własną funkcję porównywania, która porównuje słowniki według wartości kluczy nazw. Zobacz sortowanie Mini-Jak z PythonInfo Wiki

 13
Author: Matej,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2008-09-16 14:31:52
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']) 
 12
Author: forzagreen,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-17 10:29:50

Próbowałem czegoś takiego:

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

To działało również dla liczb całkowitych.

 8
Author: Sandip Agarwal,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-04-10 11:30:29

Oto alternatywne ogólne rozwiązanie-sortuje elementy dict według kluczy i wartości. Zaletą tego - nie trzeba określać kluczy, a to nadal będzie działać, jeśli niektóre klucze brakuje w niektórych słownikach.

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)
 7
Author: vvladymyrov,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2015-01-22 17:21:17

Korzystanie z pakietu pandas jest inną metodą, chociaż jego działanie na dużą skalę jest znacznie wolniejsze niż bardziej tradycyjne metody proponowane przez inne:

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

Oto kilka wartości wzorcowych dla małej listy i dużej (100k+) listy dictów:

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
 6
Author: abby sobh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-09 16:58:57

Czasami musimy użyć lower() na przykład

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}]
 5
Author: uingtea,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-14 03:21:08

Powiedzmy, że mam Słownik D z elementami poniżej. Aby posortować, wystarczy użyć kluczowego argumentu w sortowaniu, aby przekazać niestandardową funkcję jak poniżej

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
Author: SuaveShank,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-04-16 07:35:10

Oto moja odpowiedź na pytanie związane z sortowaniem po wielu kolumnach . Działa również w przypadku zdegenerowanym, w którym liczba kolumn jest tylko jedna.

 2
Author: hughdbrown,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-05-23 12:34:51

Jeśli nie potrzebujesz oryginalnego list z dictionaries, możesz zmodyfikować go na miejscu za pomocą metody sort() za pomocą niestandardowej funkcji klucza.

Funkcja klucza:

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

    return d["name"]

list do posortowania:

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

Sortowanie w miejscu:

data_one.sort(key=get_name)

Jeśli potrzebujesz oryginalnej list, wywołaj funkcję sorted() przekazując jej list i funkcję key, a następnie przypisz zwróconą sortowaną list do nowej zmiennej:

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

Drukowanie data_one i 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
Author: srig,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-12-19 17:31:30