Tri Python multicritère : key, tuples et reverse
Trie une liste Python selon plusieurs critères avec key : priorité des tuples, sens de reverse, égalités et tri stable, avec exemples et challenge.
Tu veux trier des mots par longueur, puis départager ceux qui ont la même longueur sans tenir compte des majuscules. Un reverse=True semble régler le sens du tri, jusqu'au moment où il renverse aussi le critère que tu voulais garder croissant.
En bref
Pour trier une liste Python selon plusieurs critères, donne à sorted une fonction key qui renvoie un tuple, du critère prioritaire au dernier départage. Python compare les clés de gauche à droite et conserve l'ordre d'origine quand elles sont égales. reverse=True inverse l'ordre des clés entières : pour mélanger les directions, inverse un critère numérique dans la clé ou utilise plusieurs tris stables, du critère secondaire au principal.
Comment indiquer la priorité des critères avec key ?
Le premier élément du tuple décide du classement ; le suivant ne sert qu'en cas d'égalité. Ici, la longueur passe avant le texte en minuscules.
mots = ["pear", "Bee", "ant", "bee", "Ant", "fig"]for mot in mots: print(mot, (len(mot), mot.lower()))result = sorted(mots, key=lambda mot: (len(mot), mot.lower()))print(result)print(mots)$ python3 keys.pypear (4, 'pear')Bee (3, 'bee')ant (3, 'ant')bee (3, 'bee')Ant (3, 'ant')fig (3, 'fig')['ant', 'Ant', 'Bee', 'bee', 'fig', 'pear']['pear', 'Bee', 'ant', 'bee', 'Ant', 'fig']Le mot pear arrive après tous les mots de longueur 3. Parmi ces derniers, ant précède bee, qui précède fig. La fonction de clé calcule une valeur de classement pour chaque élément, elle ne reçoit pas deux mots à comparer.
| Comparaison | Clés | Décision |
|---|---|---|
| pear / fig | (4, 'pear') / (3, 'fig') | La longueur suffit : fig avant pear |
| Bee / ant | (3, 'bee') / (3, 'ant') | Longueurs égales : le texte décide |
| ant / Ant | (3, 'ant') / (3, 'ant') | Clés égales : l'ordre initial reste |
Le tri est stable. ant était avant Ant, cet ordre reste ; Bee reste avant bee. Les majuscules ne reviennent pas comme critère caché : Python ne compare pas ensuite les mots d'origine pour les départager.
sorted renvoie une nouvelle liste. L'entrée conserve son ordre, comme le montre la dernière ligne. Cette distinction entre nouvelle liste et modification sur place revient aussi quand tu filtres des éléments pendant un parcours.
Pourquoi reverse=True inverse-t-il aussi le second critère ?
reverse=True demande un ordre décroissant sur la clé complète. Il ne vise pas seulement le premier élément du tuple.
On veut les longueurs décroissantes, puis les mots croissants à longueur égale. Comparons la tentative avec reverse à une clé dont seule la longueur change de signe.
mots = ["pear", "Bee", "ant", "bee", "Ant", "fig"]print(sorted(mots, key=lambda mot: (len(mot), mot.lower()), reverse=True))print(sorted(mots, key=lambda mot: (-len(mot), mot.lower())))$ python3 directions.py['pear', 'fig', 'Bee', 'bee', 'ant', 'Ant']['pear', 'ant', 'Ant', 'Bee', 'bee', 'fig']La première ligne place fig avant bee, puis ant. La seconde garde le texte croissant mais place les plus grandes longueurs en premier : -4 vient avant -3.
Cette négation convient à la longueur entière de nos mots. Elle ne s'applique pas à une chaîne : il n'existe pas de -mot.lower(). Évite aussi d'ajouter un reverse=True à la clé négative, ce qui renverserait de nouveau tous les critères.
Comment mélanger les directions quand le critère est une chaîne ?
Effectue le tri secondaire d'abord, puis le tri principal. La stabilité du second passage préserve l'ordre déjà obtenu à l'intérieur de chaque groupe de clés principales égales.
Cette fois, on veut les longueurs croissantes, puis le texte décroissant.
mots = ["pear", "Bee", "ant", "bee", "Ant", "fig"]secondaire = sorted(mots, key=str.lower, reverse=True)print(secondaire)result = sorted(secondaire, key=len)print(result)$ python3 passes.py['pear', 'fig', 'Bee', 'bee', 'ant', 'Ant']['fig', 'Bee', 'bee', 'ant', 'Ant', 'pear']Après le premier passage, le texte est décroissant. Le second rassemble les mots par longueur sans changer l'ordre des mots de longueur 3.
| Ordre demandé | Construction |
|---|---|
| Longueur croissante, texte croissant | Une clé (len(mot), mot.lower()) |
| Longueur décroissante, texte croissant | Une clé (-len(mot), mot.lower()) |
| Longueur croissante, texte décroissant | Texte décroissant d'abord, longueur croissante ensuite |
Avec trois critères, le même principe s'applique : dernier départage d'abord, critère principal en dernier. Écrire la priorité en toutes lettres avant le code aide à éviter l'inversion des passages.
Quelle différence entre sorted et list.sort ?
sorted construit une liste, tandis que list.sort modifie la liste existante et renvoie None. Les deux acceptent les mêmes choix de clé et de direction, et garantissent la stabilité.
mots = ["pear", "Bee", "ant"]alias = motsresult = mots.sort(key=lambda mot: (len(mot), mot.lower()))print(result)print(mots)print(alias is mots)print(sorted([], key=lambda mot: (len(mot), mot.lower())))$ python3 inplace.pyNone['ant', 'Bee', 'pear']True[]Si tu écris mots = mots.sort(...), tu remplaces donc ta référence par None. Utilise sorted si l'appelant a besoin de réutiliser l'entrée ; utilise sort si le contrat demande une modification de cette liste.
sort_ranked_words
Trie les mots selon la longueur, le texte en minuscules, puis le nombre de voyelles demandé par l'énoncé. Renvoie une nouvelle liste et conserve l'ordre initial quand toutes les clés sont égales. Le challenge ajoute un troisième départage à construire toi-même.
Questions fréquentes
Faut-il mettre lower() ou lower dans la clé ?
Pour une clé simple, key=str.lower passe la fonction au tri. Dans une clé composée, lambda mot: (len(mot), mot.lower()) calcule les deux valeurs pour le mot reçu.
reverse=True casse-t-il la stabilité ?
Non. Les éléments de clés égales gardent leur ordre d'origine, même avec reverse=True. Renverser ensuite la liste avec une tranche [::-1] renverserait aussi les égalités.
lower donne-t-il un ordre alphabétique français ?
Non. Il transforme la casse, puis les chaînes sont comparées selon leur ordre Unicode. Un classement linguistique des accents demande une politique de collation distincte. Les exemples ici utilisent des mots ASCII.
Peut-on comparer des clés avec None et des nombres ?
Un mélange non comparable peut lever TypeError. Décide d'abord où vont les valeurs manquantes et construis une clé qui les sépare avant le critère de valeur ; ne compte pas sur le tri pour deviner ce contrat.
Sources
