3417 votes

Comment trier un dictionnaire par valeur ?

J'ai un dictionnaire de valeurs lues à partir de deux champs dans une base de données : un champ de type chaîne de caractères et un champ numérique. Le champ chaîne est unique, c'est donc la clé du dictionnaire.

Je peux trier sur les clés, mais comment trier sur les valeurs ?

Note : J'ai lu la question de Stack Overflow ici. Comment trier une liste de dictionnaires par une valeur du dictionnaire ? et je pourrais probablement modifier mon code pour avoir une liste de dictionnaires, mais comme je n'ai pas vraiment besoin d'une liste de dictionnaires, je voulais savoir s'il existe une solution plus simple pour trier par ordre croissant ou décroissant.

9 votes

La structure de données du dictionnaire n'a pas d'ordre inhérent. Vous pouvez l'itérer, mais rien ne garantit que l'itération suivra un ordre particulier. C'est par conception, donc votre meilleure chance est probablement d'utiliser une autre structure de données pour la représentation.

135 votes

"sorted()" peut opérer sur des dictionnaires (et retourne une liste de clés triées), donc je pense qu'il est conscient de cela. Sans connaître son programme, il est absurde de dire à quelqu'un qu'il utilise la mauvaise structure de données. Si les recherches rapides sont ce dont vous avez besoin 90% du temps, alors un dict est probablement ce que vous voulez.

0 votes

Les trois sorties (clés, valeurs, les deux) pour le tri des dictionnaires sont couvertes ici dans un style clair et concis : stackoverflow.com/questions/16772071/sort-dict-by-value-python

5983voto

Devin Jeanpierre Points 23162

Python 3.7+ ou CPython 3.6

Les Dicts préservent l'ordre d'insertion dans Python 3.7+. Idem dans CPython 3.6, mais c'est un détail de mise en œuvre .

>>> x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
>>> {k: v for k, v in sorted(x.items(), key=lambda item: item[1])}
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

ou

>>> dict(sorted(x.items(), key=lambda item: item[1]))
{0: 0, 2: 1, 1: 2, 4: 3, 3: 4}

Python plus ancien

Il n'est pas possible de trier un dictionnaire, mais seulement d'obtenir une représentation d'un dictionnaire trié. Les dictionnaires sont par nature sans ordre, mais d'autres types, tels que les listes et les tuples, ne le sont pas. Vous avez donc besoin d'un type de données ordonné pour représenter les valeurs triées, qui sera une liste - probablement une liste de tuples.

Par exemple,

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(1))

sorted_x sera une liste de tuples triés par le deuxième élément de chaque tuple. dict(sorted_x) == x .

Et pour ceux qui souhaitent trier sur les clés au lieu des valeurs :

import operator
x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=operator.itemgetter(0))

Dans Python3, depuis le déballage n'est pas autorisé nous pouvons utiliser

x = {1: 2, 3: 4, 4: 3, 2: 1, 0: 0}
sorted_x = sorted(x.items(), key=lambda kv: kv[1])

Si vous voulez la sortie comme un dict, vous pouvez utiliser collections.OrderedDict :

import collections

sorted_dict = collections.OrderedDict(sorted_x)

46 votes

Pour connaître les délais des différents systèmes de tri des dictionnaires par valeur : writeonly.wordpress.com/2008/08/30/

181 votes

sorted_x.reverse() vous donnera un ordre décroissant (par le deuxième élément du tuple)

459 votes

Saidimu : Puisque nous utilisons déjà sorted() il est beaucoup plus efficace de passer dans l'élément reverse=True argument.

1450voto

Nas Banov Points 7293

Aussi simple que ça : sorted(dict1, key=dict1.get)

En fait, il est possible de faire un "tri par valeurs de dictionnaire". Récemment, j'ai dû faire cela dans un Code Golf (question Stack Overflow) Code golf : Tableau de fréquence des mots ). Abrégé, le problème était du genre : étant donné un texte, compter la fréquence à laquelle chaque mot est rencontré et afficher une liste des principaux mots, classés par fréquence décroissante.

Si vous construisez un dictionnaire avec les mots comme clés et le nombre d'occurrences de chaque mot comme valeur, simplifié ici comme :

from collections import defaultdict
d = defaultdict(int)
for w in text.split():
    d[w] += 1

vous pouvez alors obtenir une liste des mots, classés par fréquence d'utilisation avec sorted(d, key=d.get) - le tri itère sur les clés du dictionnaire, en utilisant le nombre d'occurrences des mots comme clé de tri .

for w in sorted(d, key=d.get, reverse=True):
    print(w, d[w])

J'écris cette explication détaillée pour illustrer ce que les gens entendent souvent par "je peux facilement trier un dictionnaire par clé, mais comment trier par valeur" - et je pense que le post original essayait de répondre à ce genre de problème. Et la solution est de faire un tri de la liste des clés, sur la base des valeurs, comme indiqué ci-dessus.

36 votes

C'est également bon mais key=operator.itemgetter(1) devrait être plus évolutive, dans un souci d'efficacité, que key=d.get

12 votes

@bli sorted_keys = sorted(d.items(), key=itemgetter(1), reverse=True) y for key, val in sorted_keys: print "%s: %d" % (key, val) - itemgetter crée une fonction lorsqu'il est appelé, vous ne l'utilisez pas directement comme dans votre exemple. Et une simple itération sur un dict utilise les clés sans les valeurs.

23 votes

Je suis venu du futur pour vous annoncer collections.Counter qui a un most_common méthode qui pourrait vous intéresser :)

1004voto

Mark Points 1621

Vous pourriez utiliser :

sorted(d.items(), key=lambda x: x[1])

Cela permet de trier le dictionnaire en fonction des valeurs de chaque entrée du dictionnaire, de la plus petite à la plus grande.

Pour le trier dans l'ordre décroissant, il suffit d'ajouter reverse=True :

sorted(d.items(), key=lambda x: x[1], reverse=True)

Entrée :

d = {'one':1,'three':3,'five':5,'two':2,'four':4}
a = sorted(d.items(), key=lambda x: x[1])    
print(a)

Sortie :

[('one', 1), ('two', 2), ('three', 3), ('four', 4), ('five', 5)]

0 votes

D'après ce que j'ai vu ( docs.python.org/2/library/ ), il existe une classe appelée OrderedDict qui peut être triée et conserver l'ordre tout en restant un dictionnaire. D'après les exemples de code, vous pouvez utiliser lambda pour le trier, mais je ne l'ai pas essayé personnellement :P

64 votes

Je préférerais key=lambda (k, v): v personnellement

0 votes

@Keyo ne devrait-il pas renvoyer une liste ordonnée de clés (triées par valeurs) et non pas une liste de mots-clés ? (k,v) tuples ? C'est ce que j'obtiens avec Python 2.7.10. @Nyxynyx ajoute le paramètre reverse=True pour trier dans l'ordre décroissant.

253voto

Roberto Bonvallet Points 6336

Les Dicts ne peuvent pas être triées, mais vous pouvez construire une liste triée à partir d'elles.

Une liste triée de valeurs de dict :

sorted(d.values())

Une liste de paires (clé, valeur), triée par valeur :

from operator import itemgetter
sorted(d.items(), key=itemgetter(1))

0 votes

Dans quel ordre sont placées les clés ayant la même valeur ? J'ai trié la liste d'abord par clés, puis par valeurs, mais l'ordre des clés ayant la même valeur ne demeure pas.

5 votes

Les Dicts peuvent maintenant être triés, à partir de CPython 3.6 et de toutes les autres implémentations Python à partir de 3.7.

174voto

mykhal Points 5873

Dans la récente version 2.7 de Python, nous disposons de la nouvelle fonction OrderedDict qui mémorise l'ordre dans lequel les éléments ont été ajoutés.

>>> d = {"third": 3, "first": 1, "fourth": 4, "second": 2}

>>> for k, v in d.items():
...     print "%s: %s" % (k, v)
...
second: 2
fourth: 4
third: 3
first: 1

>>> d
{'second': 2, 'fourth': 4, 'third': 3, 'first': 1}

Faire un nouveau dictionnaire ordonné à partir de l'original, en triant par les valeurs :

>>> from collections import OrderedDict
>>> d_sorted_by_value = OrderedDict(sorted(d.items(), key=lambda x: x[1]))

L'OrderedDict se comporte comme un dict normal :

>>> for k, v in d_sorted_by_value.items():
...     print "%s: %s" % (k, v)
...
first: 1
second: 2
third: 3
fourth: 4

>>> d_sorted_by_value
OrderedDict([('first': 1), ('second': 2), ('third': 3), ('fourth': 4)])

5 votes

Ce n'est pas le sujet de la question - il ne s'agit pas de maintenir l'ordre des clés mais de "trier par valeur".

10 votes

@Nas Banov : ce n'est PAS le tri par la clé. c'est le tri dans l'ordre, nous créons les éléments. dans notre cas, nous trions par la valeur. malheureusement, le dict à 3 éléments a été malheureusement choisi de sorte que l'ordre était le même, lorsqu'il était trié à la fois par la valeur et la clé, donc j'ai élargi l'exemple de dict.

0 votes

sorted(d.items(), key=lambda x: x[1]) Pouvez-vous expliquer ce que le x signifie, pourquoi cela peut prendre x[1] à lambda ? Pourquoi est-ce que ça ne peut pas être x[0] ? Merci beaucoup !

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