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.

3437voto

Mario Fernandez Points 8974

El sorted() La fonction prend un key= paramètre

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

Alternativement, vous pouvez utiliser operator.itemgetter au lieu de définir la fonction vous-même

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

Pour être complet, ajoutez reverse=True pour trier par ordre décroissant

newlist = sorted(list_to_be_sorted, key=itemgetter('name'), reverse=True)

54 votes

L'utilisation de la clé est non seulement plus propre mais aussi plus efficace.

5 votes

Le moyen le plus rapide serait d'ajouter une instruction newlist.reverse(). Sinon, vous pouvez définir une comparaison comme cmp=lambda x,y : - cmp(x['nom'],y['nom']).

4 votes

Si la valeur de tri est un nombre, vous pourriez dire : lambda k : (k['age'] * -1) pour obtenir un tri inversé

230voto

import operator

Pour trier la liste des dictionnaires par key='name' :

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

Pour trier la liste des dictionnaires par key='age' :

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

16 votes

Comment combiner le nom et l'âge ? (comme dans SQL ORDER BY name,age ?)

46 votes

@monojohnny : oui, il suffit que la clé renvoie un tuple, key=lambda k: (k['name'], k['age']) . (ou key=itemgetter('name', 'age') ). de tuple cmp comparera chaque élément tour à tour. C'est vraiment génial.

1 votes

Dans la documentation ( docs.python.org/2/tutorial/datastructures.html ) l'option key argument pour list.sort() n'est pas décrite. Une idée où trouver cela ?

110voto

pjz Points 11925
my_list = [{'name':'Homer', 'age':39}, {'name':'Bart', 'age':10}]

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

my_list sera maintenant ce que vous voulez.

Ou mieux :

Depuis Python 2.4, il existe une fonction key est à la fois plus efficace et plus soigné :

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

...le lambda est, IMO, plus facile à comprendre que operator.itemgetter mais votre kilométrage peut varier.

0 votes

Je veux dire une liste de dicts avec une seule clé et une seule valeur mais la clé et la valeur ne peuvent pas être définies car elles changent constamment.

1 votes

J'aurais besoin de plus d'un exemple à regarder. Essayez de soumettre une solution possible sur le stackexchange de codereview et demandez s'il existe une meilleure solution.

1 votes

@Sam si vous voulez trier par la valeur de la clé unique dans le dict, même si vous ne connaissez pas la clé, vous pouvez faire key=lambda k: list(k.values())[0]

73voto

Dologan Points 541

Si vous voulez trier la liste par plusieurs clés, vous pouvez procéder comme suit :

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

Il s'agit d'une méthode assez artisanale, puisqu'elle repose sur la conversion des valeurs en une seule représentation de chaîne de caractères pour la comparaison, mais elle fonctionne comme prévu pour les nombres, y compris les nombres négatifs (bien que vous deviez formater votre chaîne de caractères de manière appropriée, avec un espacement nul si vous utilisez des nombres).

3 votes

Trié en utilisant timsort qui est stable, vous pouvez appeler sorted plusieurs fois pour avoir un tri sur plusieurs critères

1 votes

Le commentaire de njzk2 n'était pas immédiatement clair pour moi, alors j'ai trouvé ce qui suit. Vous pouvez simplement trier deux fois comme le suggère njzk2, ou passer plusieurs arguments à operator.itemgetter dans la réponse du haut. Lien : stackoverflow.com/questions/5212870/

18 votes

Il n'est pas nécessaire de convertir en chaîne de caractères. Il suffit de retourner un tuple comme clé.

46voto

forzagreen Points 658
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'])

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