Skip to content

Trier une liste de dictionnaires par la valeur de la clé spécifique en Python

En Python, le tri d’une liste de dictionnaires avec la méthode sort() ou la fonction sorted() génère l’erreur TypeError par défaut.

En spécifiant le paramètre key de sort() ou sorted(), vous pouvez trier une liste de dictionnaires en fonction de la valeur de la clé spécifique.

Cet article décrit le contenu suivant.

  • Le tri d’une liste de dictionnaires génère une erreur par défaut
  • Spécifiez des expressions lambda pour le paramètre clé
  • Spécifiez operator.itemgetter() pour le paramètre clé
  • Trier par plusieurs clés
  • max(), min() pour une liste de dictionnaires

Les exemples de codes suivants utilisent une liste de dictionnaires avec des clés communes. Le module pprint est utilisé pour faciliter la lecture de la sortie.

import pprint

l = [{'Name': 'Alice', 'Age': 40, 'Point': 80},
     {'Name': 'Bob', 'Age': 20},
     {'Name': 'Charlie', 'Age': 30, 'Point': 70}]

Le tri d’une liste de dictionnaires génère une erreur par défaut

Le tri d’une liste de dictionnaires (dict) avec la méthode sort() ou la fonction sorted() génère l’erreur TypeError par défaut.

En effet, le dictionnaire ne prend pas en charge les comparaisons avec <, >, etc.

# sorted(l)
# TypeError: '<' not supported between instances of 'dict' and 'dict'

Spécifiez des expressions lambda pour le paramètre clé

Pour trier une liste de dictionnaires en fonction de la valeur de la clé spécifique, spécifiez le paramètre clé de la méthode sort() ou de la fonction sorted().

En spécifiant une fonction à appliquer à chaque élément de la liste, celle-ci est triée en fonction du résultat de cette fonction. Voir l’article suivant pour plus d’informations.

Dans cet exemple, vous pouvez spécifier une fonction pour obtenir la valeur d’une clé spécifique à partir du dictionnaire.

Vous pouvez définir une fonction avec def, mais il est pratique d’utiliser des expressions lambda dans un tel cas.

pprint.pprint(sorted(l, key=lambda x: x['Age']))
# [{'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

pprint.pprint(sorted(l, key=lambda x: x['Name']))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70}]

Spécifiez s’il faut trier par ordre décroissant ou croissant avec le paramètre inverse.

pprint.pprint(sorted(l, key=lambda x: x['Age'], reverse=True))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 20, 'Name': 'Bob'}]

Jusqu’à présent, les exemples utilisent sorted(), mais vous pouvez spécifier key et reverse de la même manière avec la méthode sort() de list.

Pour connaître la différence entre sort() et sorted(), consultez l’article suivant. sort() trie l’objet d’origine lui-même et sorted() crée un nouvel objet trié.

Lorsque la clé spécifiée n’existe pas

Avec la méthode indiquée ci-dessus, une erreur est générée si la clé spécifiée n’existe pas.

# sorted(l, key=lambda x: x['Point'])
# KeyError: 'Point'

Dans ce cas, utilisez la méthode get() de dict, qui renvoie la valeur par défaut pour les clés inexistantes.

Par défaut, get() renvoie None pour les clés inexistantes. Aucun n’est comparable à un nombre ou à une chaîne, donc une erreur se produit.

# sorted(l, key=lambda x: x.get('Point'))
# TypeError: '<' not supported between instances of 'int' and 'NoneType'

Vous pouvez spécifier une valeur pour une clé qui n’existe pas comme deuxième argument de get(). Les éléments dont les clés n’existent pas sont remplacés par la valeur spécifiée dans le deuxième argument et triés.

pprint.pprint(sorted(l, key=lambda x: x.get('Point', 75)))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 20, 'Name': 'Bob'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

Infinity inf est déterminé comme étant supérieur à tout autre nombre, vous pouvez donc utiliser inf et -inf pour toujours placer des éléments sans clé à la fin ou au début.

pprint.pprint(sorted(l, key=lambda x: x.get('Point', float('inf'))))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 20, 'Name': 'Bob'}]

pprint.pprint(sorted(l, key=lambda x: x.get('Point', -float('inf'))))
# [{'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

Spécifiez operator.itemgetter() pour le paramètre clé

Vous pouvez également utiliser itemgetter() du module opérateur de la bibliothèque standard. C’est plus rapide que d’utiliser une expression lambda.

import operator

pprint.pprint(sorted(l, key=operator.itemgetter('Age')))
# [{'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80}]

pprint.pprint(sorted(l, key=operator.itemgetter('Name')))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80},
#  {'Age': 20, 'Name': 'Bob'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70}]

Si la clé spécifiée n’existe pas, une erreur se produit.

# sorted(l, key=operator.itemgetter('Point'))
# KeyError: 'Point'

Trier par plusieurs clés

Voici un exemple de cas où les dictionnaires ont la même valeur pour une clé commune. Deux dictionnaires ont la valeur ‘CA’ pour la clé ‘State’.

l_dup = [{'Name': 'Alice', 'Age': 40, 'Point': 80, 'State': 'CA'},
         {'Name': 'Bob', 'Age': 20, 'State': 'NY'},
         {'Name': 'Charlie', 'Age': 30, 'Point': 70, 'State': 'CA'}]

Si les valeurs sont égales, l’ordre d’origine est conservé.

pprint.pprint(sorted(l_dup, key=operator.itemgetter('State')))
# [{'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 20, 'Name': 'Bob', 'State': 'NY'}]

Vous pouvez spécifier plusieurs arguments pour operator.itemgetter(), et si les valeurs de la première clé sont égales, elles seront comparées et triées par la valeur de la clé suivante.

pprint.pprint(sorted(l_dup, key=operator.itemgetter('State', 'Age')))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'},
#  {'Age': 20, 'Name': 'Bob', 'State': 'NY'}]

Notez que si l’ordre des arguments est différent, le résultat est également différent.

pprint.pprint(sorted(l_dup, key=operator.itemgetter('Age', 'State')))
# [{'Age': 20, 'Name': 'Bob', 'State': 'NY'},
#  {'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'}]

La même chose peut être faite avec des expressions lambda renvoyant plusieurs valeurs sous forme de tuples ou de listes.

pprint.pprint(sorted(l_dup, key=lambda x: (x['State'], x['Age'])))
# [{'Age': 30, 'Name': 'Charlie', 'Point': 70, 'State': 'CA'},
#  {'Age': 40, 'Name': 'Alice', 'Point': 80, 'State': 'CA'},
#  {'Age': 20, 'Name': 'Bob', 'State': 'NY'}]

max(), min() pour une liste de dictionnaires

Comme mentionné ci-dessus, les comparaisons avec < ou > ne sont pas prises en charge pour les dictionnaires dict, donc le passage d’une liste de dictionnaires à max() ou min() provoque une erreur.

# max(l)
# TypeError: '>' not supported between instances of 'dict' and 'dict'

Comme avec triés() et sort(), vous pouvez également spécifier le paramètre clé dans max() et min().

print(max(l, key=lambda x: x['Age']))
# {'Name': 'Alice', 'Age': 40, 'Point': 80}

print(min(l, key=lambda x: x['Age']))
# {'Name': 'Bob', 'Age': 20}

Le dictionnaire dict est renvoyé, donc si vous voulez obtenir une valeur, spécifiez une clé.

print(max(l, key=lambda x: x['Age'])['Age'])
# 40

Bien sûr, vous pouvez également utiliser operator.itemgetter().

print(max(l, key=operator.itemgetter('Age')))
# {'Name': 'Alice', 'Age': 40, 'Point': 80}