2640 votes

Comment trier une liste de dictionnaires par une valeur du dictionnaire ?

Comment trier une liste de dictionnaires par la valeur d'une clé spécifique ? Étant donné :

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

Lorsqu'ils sont triés par name il devrait devenir :

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

6 votes

Lire la réponse et continuer à regarder opérateur.itemgetter . Puis-je trier sur plusieurs valeurs dans le même processus (par exemple nous avons [{'name':'Bart', 'age':10, 'note':3},{'name':'Homer','age':10,'note':2},{'name':'Vasile‌​','age':20,'note':3}‌​] Et à utiliser : from operator import itemgetter newlist = sorted(old_list, key=itemgetter(-'note','name') EDIT : Testé, et ça marche mais je ne sais pas comment faire pour que la note soit DESC et le nom ASC.

11voto

Bejür Points 38

J'ai été un grand fan d'un filtre avec lambda. Cependant, ce n'est pas la meilleure option si l'on considère la complexité temporelle.

Première option

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

Deuxième option

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

Comparaison rapide des temps d'exécution

# 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 boucles, meilleur de 3 : 0.736 µsec par boucle

# 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 boucles, meilleur de 3 : 0.438 µsec par boucle

10voto

Sandip Agarwal Points 851

J'ai essayé quelque chose comme ça :

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

Cela a également fonctionné pour les nombres entiers.

9voto

swac Points 1

Si les performances sont un problème, j'utiliserais operator.itemgetter au lieu de lambda car les fonctions intégrées sont plus rapides que les fonctions créées à la main. Le site itemgetter semble être environ 20% plus rapide que la fonction lambda sur la base de mes tests.

Desde https://wiki.python.org/moin/PythonSpeed :

De même, les fonctions intégrées s'exécutent plus rapidement que les fonctions équivalentes construites à la main. Par exemple, map(operator.add, v1, v2) est plus rapide que map(lambda x,y : x+y, v1, v2).

Voici une comparaison de la vitesse de tri en utilisant lambda vs itemgetter .

import random
import operator

# Create a list of 100 dicts with random 8-letter names and random ages from 0 to 100.
l = [{'name': ''.join(random.choices(string.ascii_lowercase, k=8)), 'age': random.randint(0, 100)} for i in range(100)]

# Test the performance with a lambda function sorting on name
%timeit sorted(l, key=lambda x: x['name'])
13 µs ± 388 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# Test the performance with itemgetter sorting on name
%timeit sorted(l, key=operator.itemgetter('name'))
10.7 µs ± 38.1 ns per loop (mean ± std. dev. of 7 runs, 100000 loops each)

# Check that each technique produces the same sort order
sorted(l, key=lambda x: x['name']) == sorted(l, key=operator.itemgetter('name'))
True

Les deux techniques trient la liste dans le même ordre (vérifié par l'exécution de la dernière instruction du bloc de code), mais la première est un peu plus rapide.

4voto

hughdbrown Points 15770

Voici ma réponse à une question connexe sur le tri par colonnes multiples . Elle fonctionne également pour le cas dégénéré où le nombre de colonnes n'est que de un.

1voto

Tms91 Points 84

Comme indiqué par @Claudiu à @monojohnny dans la section commentaire de cette réponse ,
dado:

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

pour trier la liste des dictionnaires par clé 'age' , 'name'
(comme dans l'instruction SQL ORDER BY age, name ), vous pouvez utiliser :

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

ou, de même

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

print(newlist)

[{nom : 'Bart', 'âge' : 10},
{nom : 'Milhouse', âge : 10},
{nom : 'Homer', 'âge' : 39}]

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X