Trier une table
Introduction
Trier une table, c'est en réordonner les lignes selon une colonne (ou plusieurs). Cette opération courante a deux utilités principales : rendre les données lisibles pour un humain (classement alphabétique, palmarès) et préparer la table à d'autres opérations (recherche dichotomique, jointure ordonnée).
Imaginez une main de cartes qu'on aligne par valeur croissante, ou une liste de prénoms qu'on range par ordre alphabétique : trier, c'est exactement cela — mais à grande échelle et selon n'importe quel critère choisi.
précise que vous pouvez utiliser une fonction de tri
intégrée à la bibliothèque standard — pas besoin de réécrire un algorithme
de tri. C'est ce que nous ferons avec la fonction sorted() de Python.
La fonction sorted()
sorted(iterable) renvoie une nouvelle liste contenant les éléments de
l'itérable, triés par ordre croissant. C'est la version la plus simple :
nombres = [3, 1, 4, 1, 5, 9, 2, 6]
print(sorted(nombres))
# [1, 1, 2, 3, 4, 5, 6, 9]
sorted()ne modifie pas la liste d'origine — elle retourne une copie
triée. Pour un tri en place qui modifie la liste, utilisez la méthode
liste.sort().Que retourne sorted(3, 1, 2) ?
Trier une table par une colonne
Sur une liste de dictionnaires, sorted() seul ne sait pas comparer — un
dictionnaire {"nom": "Alice", ...} n'a pas d'ordre intrinsèque. Il faut
indiquer selon quelle colonne trier, via le paramètre key=.
key= attend une fonction qui, appliquée à une ligne, retourne la valeur
à utiliser pour la comparaison. On utilise pour cela une fonction lambda
ou une fonction nommée :
lambda x: ... se lit comme une mini-fonction
sans nom : lambda e: e["nom"] équivaut à une fonction qui prendrait e
en paramètre et renverrait e["nom"]. Pratique quand la fonction est trop
courte pour mériter un def. La notion lambda est étudiée en détail au
chapitre PG — Langages et programmation ; ici, retenez juste la lecture.eleves = [
{"nom": "Chloé", "age": 16, "classe": "1G2"},
{"nom": "Alice", "age": 16, "classe": "1G2"},
{"nom": "Dimitri", "age": 17, "classe": "1G2"},
{"nom": "Bob", "age": 17, "classe": "1G3"},
]
# Tri par nom (ordre alphabétique)
par_nom = sorted(eleves, key=lambda e: e["nom"])
for e in par_nom:
print(e["nom"])
# Alice
# Bob
# Chloé
# Dimitri
lambda e: e["nom"] est une mini-fonction sans nom, qu'on définit à la
volée : appliquée à une ligne e, elle retourne e["nom"]. C'est elle qui
sert de critère de comparaison.
operator.itemgetter("nom") qui fait la même chose
mais demande un import. lambda est suffisant pour ce qu'on fait.Tri par colonne numérique
Trier par âge fonctionne exactement de la même façon, à condition que la colonne soit numérique :
Sortie :
16 Chloé
16 Alice
17 Dimitri
17 Bob
age est encore une chaîne (ex. "17"), le tri se fait dans
l'ordre lexicographique des chaînes : "10" < "9" ! Convertir avant
avec int() ou utiliser key=lambda e: int(e["age"]).Tri descendant
Pour inverser l'ordre, ajouter reverse=True :
par_age_desc = sorted(eleves, key=lambda e: e["age"], reverse=True)
for e in par_age_desc:
print(e["age"], e["nom"])
# 17 Dimitri
# 17 Bob
# 16 Chloé
# 16 Alice
Comment trier la table par nom dans l'ordre Z→A ?
Ordre stable
Une propriété essentielle de sorted() : c'est un tri stable. Cela
signifie que les éléments ayant la même valeur de clé conservent leur
ordre relatif d'origine. C'est l'équivalent d'un bibliothécaire qui range
des livres par auteur sans bouleverser l'ordre des éditions dans chaque
auteur.
Reprenez l'exemple précédent. Dans la table d'entrée, Chloé apparaît avant Alice. Après le tri par âge, Chloé et Alice ont toutes deux 16 ans — et le tri stable les place dans le même ordre que dans l'entrée : Chloé d'abord, puis Alice.
Tri par plusieurs critères
Tri par classe, puis par nom à l'intérieur de chaque classe :
# Méthode 1 : tris successifs (du moins prioritaire au plus prioritaire)
par_nom = sorted(eleves, key=lambda e: e["nom"])
par_classe_puis_nom = sorted(par_nom, key=lambda e: e["classe"])
for e in par_classe_puis_nom:
print(e["classe"], e["nom"])
# 1G2 Alice
# 1G2 Chloé
# 1G2 Dimitri
# 1G3 Bob
par_classe_puis_nom = sorted(
eleves,
key=lambda e: (e["classe"], e["nom"]),
)
sort() vs sorted()
| Aspect | sorted(liste) | liste.sort() |
|---|---|---|
| Type de retour | Nouvelle liste triée | None |
| Effet sur l'original | Aucun | Trié en place |
| Utilisable sur | Tout itérable | Liste seulement |
| Quand l'utiliser | Si on veut garder l'original | Si on veut économiser la mémoire |
nombres = [3, 1, 2]
nombres.sort()
print(nombres) # [1, 2, 3]
nombres.sort(reverse=True)
print(nombres) # [3, 2, 1]
Cas particuliers et pièges
- Tri sur une chaîne accentuée :
"é"n'est pas placé entre"e"et"f"mais après tous les caractères ASCII. Pour un tri linguistique correct, utiliser le modulelocale(hors programme). - Mélanger types et
None:sorted([1, None, 2])lèveTypeError. Filtrer ou normaliser avant. - Sensibilité à la casse :
"alice" > "Bob"en ASCII (minuscules > majuscules). Pour un tri insensible :key=lambda e: e["nom"].lower().
Pour aller plus loin
Les algorithmes de tri que vous étudierez en algorithmique
( : tri par insertion, tri par sélection) sont au cœur de
ce que fait sorted() — mais Python utilise en réalité un tri plus
sophistiqué (Timsort) dont la complexité est .