Comment utiliser sorted () et sort () en Python

Comment utiliser sorted () et sort () en Python

Tous les programmeurs devront écrire du code pour trier les éléments ou les données à un moment donné. Le tri peut être essentiel à l'expérience utilisateur dans votre application, qu'il s'agisse de commander l'activité la plus récente d'un utilisateur par horodatage ou de mettre une liste des destinataires des e-mails par ordre alphabétique par nom de famille. La fonctionnalité de tri Python offre des fonctionnalités robustes pour effectuer un tri de base ou personnaliser la commande à un niveau granulaire.

Dans ce guide, vous apprendrez à trier différents types de données dans différentes structures de données, à personnaliser l'ordre et à utiliser deux méthodes de tri différentes en Python.

À la fin de ce didacticiel, vous saurez comment:

  • Implémenter le tri et l'ordre de base Python sur les structures de données

  • Différenciersorted() et.sort()

  • Personnalisez un ordre de tri complexe dans votre code en fonction d'exigences uniques

Pour ce didacticiel, vous aurez besoin d'une compréhension de base delists and tuples ainsi que desets. Ces structures de données seront utilisées dans ce didacticiel et certaines opérations de base seront effectuées sur elles. De plus, ce didacticiel utilise Python 3, donc la sortie d'exemple dans ce didacticiel peut varier légèrement si vous utilisez Python 2.

Free Bonus:Click here to get access to a chapter from Python Tricks: The Book qui vous montre les meilleures pratiques de Python avec des exemples simples que vous pouvez appliquer instantanément pour écrire du code + Pythonic plus beau.

Classement des valeurs avecsorted()

Pour commencer avec le tri Python, vous allez d'abord voir comment trier les données numériques et les données de chaîne.

Tri des numéros

Vous pouvez utiliser Python pour trier une liste en utilisantsorted(). Dans cet exemple, une liste d'entiers est définie, puissorted() est appelé avec la variablenumbers comme argument:

>>>

>>> numbers = [6, 9, 3, 1]
>>> sorted(numbers)
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]

La sortie de ce code est une nouvelle liste triée. Lorsque la variable d'origine est imprimée, les valeurs initiales restent inchangées.

Cet exemple montre quatre caractéristiques importantes desorted():

  1. La fonctionsorted() n'avait pas besoin d'être définie. Il s'agit d'une fonction intégrée disponible dans une installation standard de Python.

  2. sorted(), sans arguments ou paramètres supplémentaires, classe les valeurs ennumbers dans un ordre croissant, c'est-à-dire du plus petit au plus grand.

  3. La variable d'originenumbers est inchangée carsorted() fournit une sortie triée et ne change pas la valeur d'origine en place.

  4. Lorsquesorted() est appelé, il fournit une liste ordonnée comme valeur de retour.

Ce dernier point signifie quesorted() peut être utilisé sur une liste, et la sortie peut être immédiatement affectée à une variable:

>>>

>>> numbers = [6, 9, 3, 1]
>>> numbers_sorted = sorted(numbers)
>>> numbers_sorted
[1, 3, 6, 9]
>>> numbers
[6, 9, 3, 1]

Dans cet exemple, il y a maintenant une nouvelle variablenumbers_sorted qui stockait la sortie desorted().

Vous pouvez confirmer toutes ces observations en appelanthelp() sursorted(). Les arguments optionnelskey etreverse seront traités plus tard dans le didacticiel:

>>>

>>> # Python 3
>>> help(sorted)
Help on built-in function sorted in module builtins:

sorted(iterable, /, *, key=None, reverse=False)
    Return a new list containing all items from the iterable in ascending order.

    A custom key function can be supplied to customize the sort order, and the
    reverse flag can be set to request the result in descending order.

Technical Detail: Si vous effectuez la transition depuis Python 2 et que vous connaissez sa fonction du même nom, vous devez être conscient de quelques changements importants dans Python 3:

  1. Lessorted() de Python 3 n'ont pas de paramètrecmp. Au lieu de cela, seulkey est utilisé pour introduire une logique de tri personnalisée.

  2. key etreverse doivent être passés comme arguments de mot-clé, contrairement à Python 2, où ils pourraient être passés en tant qu'arguments de position.

Si vous avez besoin de convertir une fonction Python 2cmp en fonctionkey, consultezfunctools.cmp_to_key(). Ce tutoriel ne couvrira aucun exemple utilisant Python 2.

sorted() peut être utilisé sur des tuples et des ensembles de manière très similaire:

>>>

>>> numbers_tuple = (6, 9, 3, 1)
>>> numbers_set = {5, 5, 10, 1, 0}
>>> numbers_tuple_sorted = sorted(numbers_tuple)
>>> numbers_set_sorted = sorted(numbers_set)
>>> numbers_tuple_sorted
[1, 3, 6, 9]
>>> numbers_set_sorted
[0, 1, 5, 10]

Notez que même si l'entrée était un ensemble et un tuple, la sortie est une liste carsorted() renvoie une nouvelle liste par définition. L'objet retourné peut être converti en un nouveau type s'il doit correspondre au type d'entrée. Soyez prudent si vous essayez de convertir la liste résultante en un ensemble, car un ensemble par définition n'est pas ordonné:

>>>

>>> numbers_tuple = (6, 9, 3, 1)
>>> numbers_set = {5, 5, 10, 1, 0}
>>> numbers_tuple_sorted = sorted(numbers_tuple)
>>> numbers_set_sorted = sorted(numbers_set)
>>> numbers_tuple_sorted
[1, 3, 6, 9]
>>> numbers_set_sorted
[0, 1, 5, 10]
>>> tuple(numbers_tuple_sorted)
(1, 3, 6, 9)
>>> set(numbers_set_sorted)
{0, 1, 10, 5}

La valeurnumbers_set_sorted lorsqu'elle est convertie enset n'est pas ordonnée, comme prévu. L'autre variable,numbers_tuple_sorted, a conservé l'ordre de tri.

Tri des chaînes

Les typesstr sont triés de la même manière que les autres itérables, comme list et tuple. L'exemple ci-dessous montre commentsorted() parcourt chaque caractère de la valeur qui lui est passée et les classe dans la sortie:

>>>

>>> string_number_value = '34521'
>>> string_value = 'I like to sort'
>>> sorted_string_number = sorted(string_number_value)
>>> sorted_string = sorted(string_value)
>>> sorted_string_number
['1', '2', '3', '4', '5']
>>> sorted_string
[' ', ' ', ' ', 'I', 'e', 'i', 'k', 'l', 'o', 'o', 'r', 's', 't', 't']

sorted() traitera unstr comme une liste et parcourra chaque élément. Dans unstr, chaque élément signifie chaque caractère dustr. sorted() ne traitera pas une phrase différemment et triera chaque caractère, y compris les espaces.

.split() peut changer ce comportement et nettoyer la sortie, et.join() peut tout remettre ensemble. Nous couvrirons l'ordre spécifique de la sortie et pourquoi il en est ainsi sous peu:

>>>

>>> string_value = 'I like to sort'
>>> sorted_string = sorted(string_value.split())
>>> sorted_string
['I', 'like', 'sort', 'to']
>>> ' '.join(sorted_string)
'I like sort to'

La phrase originale de cet exemple est convertie en une liste de mots au lieu de la laisser sous forme destr. Cette liste est ensuite triée et combinée pour former à nouveau unstr au lieu d'une liste.

Limitations et accrochages avec le tri Python

Il convient de noter certaines limitations et comportements étranges qui peuvent survenir lorsque vous utilisez Python pour trier des valeurs en plus des entiers.

Les listes avec des types de données non comparables ne peuvent pas êtresorted()

Il existe des types de données qui ne peuvent pas être comparés les uns aux autres en utilisant uniquementsorted() car ils sont trop différents. Python renverra une erreur si vous essayez d'utilisersorted() sur une liste contenant des données non comparables. Dans cet exemple, unNone et unint dans la même liste ne peuvent pas être triés en raison de leur incompatibilité:

>>>

>>> mixed_types = [None, 0]
>>> sorted(mixed_types)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: '<' not supported between instances of 'int' and 'NoneType'

Cette erreur montre pourquoi Python ne peut pas trier les valeurs qui lui sont attribuées. Il essaie de mettre les valeurs dans l'ordre en utilisant l'opérateur inférieur à (<) pour déterminer quelle valeur est inférieure dans l'ordre de tri. Vous pouvez répliquer cette erreur en comparant manuellement les deux valeurs:

>>>

>>> None < 0
Traceback (most recent call last):
  File "", line 1, in 
TypeError: '<' not supported between instances of 'NoneType' and 'int'

Le mêmeTypeError est généré lorsque vous essayez de comparer deux valeurs non comparables sans utilisersorted().

Si les valeurs de la liste peuvent être comparées et ne lèveront pas deTypeError, alors la liste peut être triée. Cela empêche de trier les itérables avec des valeurs intrinsèquement non ordonnables et de produire une sortie qui peut ne pas avoir de sens.

Par exemple, le nombre1 doit-il précéder le motapple? Cependant, si un itérable contient une combinaison d'entiers et de chaînes qui sont tous des nombres, ils peuvent être convertis en types de données comparables en utilisant une compréhension de liste:

>>>

>>> mixed_numbers = [5, "1", 100, "34"]
>>> sorted(mixed_numbers)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: '<' not supported between instances of 'str' and 'int'
>>> # List comprehension to convert all values to integers
>>> [int(x) for x in mixed_numbers]
[5, 1, 100, 34]
>>> sorted([int(x) for x in mixed_numbers])
[1, 5, 34, 100]

Chaque élément demixed_numbers est appeléint() pour convertir toutes les valeursstr en valeursint. sorted() est alors appelé et peut comparer avec succès chaque élément et fournir une sortie triée.

Python peut également implicitement convertir une valeur en un autre type. Dans l'exemple ci-dessous, l'évaluation de1 <= 0 est une fausse déclaration, donc la sortie de l'évaluation seraFalse. Le nombre1 peut être converti enTrue en tant que typebool, tandis que0 se convertit enFalse.

Même si les éléments de la liste semblent différents, ils peuvent tous être convertis en booléens (True ouFalse) et comparés les uns aux autres en utilisantsorted():

>>>

>>> similar_values = [False, 0, 1, 'A' == 'B', 1 <= 0]
>>> sorted(similar_values)
[False, 0, False, False, 1]

'A' == 'B' et1 <= 0 sont convertis enFalse et renvoyés dans la sortie ordonnée.

Cet exemple illustre un aspect important du tri:sort stability. En Python, lorsque vous triez des valeurs égales, elles conserveront leur ordre d'origine dans la sortie. Même si les1 ont bougé, toutes les autres valeurs sont égales afin qu'elles conservent leur ordre d'origine les unes par rapport aux autres. Dans l'exemple ci-dessous, toutes les valeurs sont considérées comme égales et conserveront leur position d'origine:

>>>

>>> false_values = [False, 0, 0, 1 == 2, 0, False, False]
>>> sorted(false_values)
[False, 0, 0, False, 0, False, False]

Si vous inspectez l'ordre d'origine et la sortie triée, vous verrez que1 == 2 est converti enFalse et que toute la sortie triée est dans l'ordre d'origine.

Lorsque vous triez des chaînes, la casse compte

sorted() peut être utilisé sur une liste de chaînes pour trier les valeurs par ordre croissant, ce qui semble être alphabétique par défaut:

>>>

>>> names = ['Harry', 'Suzy', 'Al', 'Mark']
>>> sorted(names)
['Al', 'Harry', 'Mark', 'Suzy']

Cependant, Python utilise lesUnicode Code Point de la première lettre de chaque chaîne pour déterminer l'ordre de tri croissant. Cela signifie quesorted() ne traitera pas les nomsAl etal de la même manière. Cet exemple utiliseord() pour renvoyer le point de code Unicode de la première lettre de chaque chaîne:

>>>

>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case)
['Mark', 'Suzy', 'al', 'harry']
>>> # List comprehension for Unicode Code Point of first letter in each word
>>> [(ord(name[0]), name[0]) for name in sorted(names_with_case)]
[(77, 'M'), (83, 'S'), (97, 'a'), (104, 'h')]

name[0] renvoie le premier caractère de chaque élément desorted(names_with_case) etord() fournit le point de code Unicode. Même sia précèdeM dans l'alphabet, le point de code pourM vient avanta, donc la sortie triée aM en premier.

Si la première lettre est la même, alorssorted() utilisera le deuxième caractère pour déterminer l'ordre, et le troisième caractère si c'est le même, et ainsi de suite, jusqu'à la fin de la chaîne:

>>>

>>> very_similar_strs = ['hhhhhd', 'hhhhha', 'hhhhhc','hhhhhb']
>>> sorted(very_similar_strs)
['hhhhha', 'hhhhhb', 'hhhhhc', 'hhhhhd']

Chaque valeur devery_similar_strs est identique sauf pour le dernier caractère. sorted() comparera les chaînes, et comme les cinq premiers caractères sont identiques, la sortie sera basée sur le sixième caractère.

Les chaînes qui contiennent des valeurs identiques finiront par être triées du plus court au plus long car les chaînes plus courtes n'ont pas d'éléments à comparer avec les chaînes plus longues:

>>>

>>> different_lengths = ['hhhh', 'hh', 'hhhhh','h']
>>> sorted(different_lengths)
['h', 'hh', 'hhhh', 'hhhhh']

La chaîne la plus courte,h, est ordonnée en premier avec la plus longue,hhhhh, ordonnée en dernier.

Utilisation desorted() avec un argumentreverse

Comme indiqué dans la documentation dehelp() poursorted(), il existe un argument de mot-clé facultatif appeléreverse, qui modifiera le comportement de tri en fonction du booléen qui lui est attribué. Sireverse est affecté àTrue, alors le tri sera dans l'ordre décroissant:

>>>

>>> names = ['Harry', 'Suzy', 'Al', 'Mark']
>>> sorted(names)
['Al', 'Harry', 'Mark', 'Suzy']
>>> sorted(names, reverse=True)
['Suzy', 'Mark', 'Harry', 'Al']

La logique de tri reste la même, ce qui signifie que les noms sont toujours triés par leur première lettre. Mais la sortie a été inversée avec le mot-cléreverse défini surTrue.

LorsqueFalse est attribué, l'ordre restera croissant. N'importe lequel des exemples précédents peut être utilisé pour voir le comportement de l'inversion en utilisant à la foisTrue ouFalse:

>>>

>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case, reverse=True)
['harry', 'al', 'Suzy', 'Mark']
>>> similar_values = [False, 1, 'A' == 'B', 1 <= 0]
>>> sorted(similar_values, reverse=True)
[1, False, False, False]
>>> numbers = [6, 9, 3, 1]
>>> sorted(numbers, reverse=False)
[1, 3, 6, 9]

sorted() Avec un argumentkey

L'un des composants les plus puissants desorted() est l'argument mot-clé appelékey. Cet argument attend qu'une fonction lui soit transmise, et cette fonction sera utilisée sur chaque valeur de la liste en cours de tri pour déterminer l'ordre résultant.

Pour illustrer un exemple de base, supposons que l'exigence de commande d'une liste spécifique est la longueur des chaînes de la liste, de la plus courte à la plus longue. La fonction pour renvoyer la longueur d'une chaîne,len(), sera utilisée avec l'argumentkey:

>>>

>>> word = 'paper'
>>> len(word)
5
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=len)
['pie', 'book', 'banana', 'Washington']

L'ordre résultant est une liste avec un ordre de chaîne du plus court au plus long. La longueur de chaque élément de la liste est déterminée parlen(), puis renvoyée par ordre croissant.

Revenons à l'exemple précédent de tri par première lettre lorsque le cas est différent. key peut être utilisé pour résoudre ce problème en convertissant la chaîne entière en minuscules:

>>>

>>> names_with_case = ['harry', 'Suzy', 'al', 'Mark']
>>> sorted(names_with_case)
['Mark', 'Suzy', 'al', 'harry']
>>> sorted(names_with_case, key=str.lower)
['al', 'harry', 'Mark', 'Suzy']

Les valeurs de sortie n'ont pas été converties en minuscules carkey ne manipule pas les données de la liste d'origine. Pendant le tri, la fonction passée àkey est appelée sur chaque élément pour déterminer l'ordre de tri, mais les valeurs d'origine seront dans la sortie.

Il existe deux limitations principales lorsque vous utilisez des fonctions avec l'argumentkey.

Tout d'abord, le nombre d'arguments requis dans la fonction passée àkey doit être égal à un.

L'exemple ci-dessous montre la définition d'une fonction d'addition qui prend deux arguments. Lorsque cette fonction est utilisée danskey sur une liste de nombres, elle échoue car il manque un deuxième argument. Chaque fois queadd() est appelé pendant le tri, il ne reçoit qu'un seul élément de la liste à la fois:

>>>

>>> def add(x, y):
...     return x + y
...
>>> values_to_add = [1, 2, 3]
>>> sorted(values_to_add, key=add)
Traceback (most recent call last):
  File "", line 1, in 
TypeError: add() missing 1 required positional argument: 'y'

La deuxième limitation est que la fonction utilisée aveckey doit être capable de gérer toutes les valeurs de l'itérable. Par exemple, vous avez une liste de nombres représentés sous forme de chaînes à utiliser danssorted(), etkey va essayer de les convertir en nombres en utilisantint. Si une valeur de l'itérable ne peut pas être convertie en un entier, la fonction échouera:

>>>

>>> values_to_cast = ['1', '2', '3', 'four']
>>> sorted(values_to_cast, key=int)
Traceback (most recent call last):
  File "", line 1, in 
ValueError: invalid literal for int() with base 10: 'four'

Chaque valeur numérique en tant questr peut être convertie enint, mais pasfour. Cela provoque le déclenchement deValueError et explique quefour ne peut pas être converti enint car il n'est pas valide.

La fonctionnalitékey est extrêmement puissante car presque toutes les fonctions, intégrées ou définies par l'utilisateur, peuvent être utilisées pour manipuler l'ordre de sortie.

Si la condition de commande est d'ordonner un itérable par la dernière lettre de chaque chaîne (et si la lettre est la même, alors d'utiliser la lettre suivante), alors unfunction peut être défini puis utilisé dans le tri. L'exemple ci-dessous définit une fonction qui inverse la chaîne qui lui est passée, puis cette fonction est utilisée comme argument pourkey:

>>>

>>> def reverse_word(word):
...     return word[::-1]
...
>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=reverse_word)
['banana', 'pie', 'book', 'Washington']

La syntaxe de la trancheword[::-1] est utilisée pour inverser une chaîne. Chaque élément aurareverse_word() appliqué, et l'ordre de tri sera basé sur les caractères du mot en arrière.

Au lieu d'écrire une fonction autonome, vous pouvez utiliser une fonctionlambda définie dans l'argumentkey.

Unlambda est une fonction anonyme qui:

  1. Doit être défini en ligne

  2. N'a pas de nom

  3. Ne peut pas contenirstatements

  4. S'exécutera comme une fonction

Dans l'exemple ci-dessous, lekey est défini comme unlambda sans nom, l'argument pris par leslambda estx etx[::-1] est l'opération qui sera effectuée sur l'argument:

>>>

>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=lambda x: x[::-1])
['banana', 'pie', 'book', 'Washington']

x[::-1] est appelé sur chaque élément et inverse le mot. Cette sortie inversée est ensuite utilisée pour le tri, mais les mots d'origine sont toujours renvoyés.

Si l'exigence change et que l'ordre doit également être inversé, le mot cléreverse peut être utilisé avec l'argumentkey:

>>>

>>> words = ['banana', 'pie', 'Washington', 'book']
>>> sorted(words, key=lambda x: x[::-1], reverse=True)
['Washington', 'book', 'pie', 'banana']

Les fonctionslambda sont également utiles lorsque vous devez trier les objetsclass en fonction d'une propriété. Si vous avez un groupe d'élèves et que vous devez les trier par leur note finale, de la plus haute à la plus basse, alors unlambda peut être utilisé pour obtenir la propriétégrade desclass:

>>>

>>> from collections import namedtuple

>>> StudentFinal = namedtuple('StudentFinal', 'name grade')
>>> bill = StudentFinal('Bill', 90)
>>> patty = StudentFinal('Patty', 94)
>>> bart = StudentFinal('Bart', 89)
>>> students = [bill, patty, bart]
>>> sorted(students, key=lambda x: getattr(x, 'grade'), reverse=True)
[StudentFinal(name='Patty', grade=94), StudentFinal(name='Bill', grade=90), StudentFinal(name='Bart', grade=89)]

Cet exemple utilisenamedtuple pour produire des classes avec les attributsname etgrade. Lelambda appellegetattr() sur chaque élément et renvoie la valeur degrade.

reverse est défini surTrue pour que la sortie ascendante soit inversée pour être décroissante afin que les notes les plus élevées soient classées en premier.

Les possibilités sont infinies quant à la façon dont le classement peut être effectué lorsque vous tirez parti des arguments de mots cléskey etreverse sursorted(). Le code peut être maintenu propre et court lorsque vous utilisez unlambda de base pour une petite fonction, ou vous pouvez écrire une toute nouvelle fonction, l'importer et l'utiliser dans l'argument clé.

Classement des valeurs avec.sort()

Le.sort() nommé de manière très similaire diffère un peu dusorted() intégré. Ils accomplissent plus ou moins la même chose, mais la documentation dehelp() pourlist.sort() met en évidence deux des différences les plus critiques entre.sort() etsorted():

>>>

>>> # Python2
Help on method_descriptor:

sort(...)
    L.sort(cmp=None, key=None, reverse=False) -- stable sort *IN PLACE*;
    cmp(x, y) -> -1, 0, 1

>>> # Python3
>>> help(list.sort)
Help on method_descriptor:

sort(...)
    L.sort(key=None, reverse=False) -> None -- stable sort *IN PLACE*

Premièrement, sort est une méthode de la classelist et ne peut être utilisée qu'avec des listes. Ce n'est pas un intégré avec un itérable passé.

Deuxièmement,.sort() renvoieNone et modifie les valeurs en place. Examinons les impacts de ces deux différences de code:

>>>

>>> values_to_sort = [5, 2, 6, 1]
>>> # Try to call .sort() like sorted()
>>> sort(values_to_sort)
Traceback (most recent call last):
  File "", line 1, in 
NameError: name 'sort' is not defined

>>> # Try to use .sort() on a tuple
>>> tuple_val = (5, 1, 3, 5)
>>> tuple_val.sort()
Traceback (most recent call last):
  File "", line 1, in 
AttributeError: 'tuple' object has no attribute 'sort'

>>> # Sort the list and assign to new variable
>>> sorted_values = values_to_sort.sort()
>>> print(sorted_values)
None

>>> # Print original variable
>>> print(values_to_sort)
[1, 2, 5, 6]

Il existe des différences assez dramatiques dans le fonctionnement de.sort() par rapport àsorted() dans cet exemple de code:

  1. Il n'y a pas de sortie ordonnée de.sort(), donc l'affectation à une nouvelle variable ne transmet qu'un typeNone.

  2. La listevalues_to_sort a été modifiée en place et l'ordre d'origine n'est en aucun cas conservé.

Ces différences de comportement font que.sort() etsorted() ne sont absolument pas interchangeables dans le code, et ils peuvent produire des résultats extrêmement inattendus si l'un est utilisé de la mauvaise manière.

.sort() a les mêmes arguments de mot-clé facultatifskey etreverse qui produisent la même fonctionnalité robuste quesorted(). Ici, vous pouvez trier une liste d'expressions par la deuxième lettre du troisième mot et retourner la liste à l'envers:

>>>

>>> phrases = ['when in rome',
...     'what goes around comes around',
...     'all is fair in love and war'
...     ]
>>> phrases.sort(key=lambda x: x.split()[2][1], reverse=True)
>>> phrases
['what goes around comes around', 'when in rome', 'all is fair in love and war']

Dans cet exemple, unlambda est utilisé pour effectuer les opérations suivantes:

  1. Divisez chaque phrase en une liste de mots

  2. Trouvez le troisième élément, ou mot dans ce cas

  3. Trouvez la deuxième lettre de ce mot

Quand utilisersorted() et quand utiliser.sort()

Vous avez vu les différences entresorted() et.sort(), mais quand utilisez-vous lequel?

Disons qu'il y a une course de 5 km à venir: le premier Python 5k annuel. Les données de la course doivent être saisies et triées. Les données qui doivent être capturées sont le numéro de dossard du coureur et le nombre de secondes nécessaires pour terminer la course:

>>>

>>> from collections import namedtuple

>>> Runner = namedtuple('Runner', 'bibnumber duration')

Lorsque les coureurs franchissent la ligne d'arrivée, chaqueRunner sera ajouté à une liste appeléerunners. Dans les courses de 5 km, tous les coureurs ne franchissent pas la ligne de départ en même temps, donc la première personne à franchir la ligne d'arrivée n'est peut-être pas la personne la plus rapide:

>>>

>>> runners = []
>>> runners.append(Runner('2528567', 1500))
>>> runners.append(Runner('7575234', 1420))
>>> runners.append(Runner('2666234', 1600))
>>> runners.append(Runner('2425234', 1490))
>>> runners.append(Runner('1235234', 1620))
>>> # Thousands and Thousands of entries later...
>>> runners.append(Runner('2526674', 1906))

Chaque fois qu'un coureur franchit la ligne d'arrivée, son numéro de dossard et sa durée totale en secondes sont ajoutés àrunners.

Maintenant, le programmeur consciencieux chargé de gérer les données de résultat voit cette liste, sait que les 5 meilleurs participants les plus rapides sont les gagnants qui obtiennent des prix, et les coureurs restants seront triés par temps le plus rapide.

Il n'y a aucune exigence pour plusieurs types de tri par divers attributs. La liste est d'une taille raisonnable. Il n'est pas question de stocker la liste quelque part. Triez simplement par durée et saisissez les cinq participants ayant la durée la plus faible:

>>>

>>> runners.sort(key=lambda x: getattr(x, 'duration'))
>>> top_five_runners = runners[:5]

Le programmeur choisit d'utiliser unlambda dans l'argumentkey pour obtenir l'attributduration de chaque coureur et trierrunners en place en utilisant.sort(). Une foisrunners trié, les 5 premiers éléments sont stockés danstop_five_runners.

Mission accomplie! Le directeur de course arrive et informe le programmeur que depuis que la version actuelle de Python est la 3.7, ils ont décidé que chaque trente-septième personne qui franchirait la ligne d'arrivée obtiendrait un sac de sport gratuit.

À ce stade, le programmeur commence à transpirer car la liste des coureurs a été modifiée de manière irréversible. Il n'y a aucun moyen de récupérer la liste d'origine des coureurs dans l'ordre où ils ont terminé et de trouver chaque trente-septième personne.

Si vous travaillez avec des données importantes et qu'il existe même une faible possibilité que les données d'origine aient besoin d'être récupérées, alors.sort() n'est pas la meilleure option. Si les données sont une copie, si ce sont des données de travail sans importance, ou si personne ne voudra les perdre parce qu'elles peuvent être récupérées, alors.sort() peut être une bonne option.

Alternativement, les coureurs auraient pu être triés en utilisantsorted() et en utilisant les mêmeslambda:

>>>

>>> runners_by_duration = sorted(runners, key=lambda x: getattr(x, 'duration'))
>>> top_five_runners = runners_by_duration[:5]

Dans ce scénario avecsorted(), la liste d'origine des coureurs est toujours intacte et n'a pas été écrasée. L'exigence impromptue de trouver chaque trente-septième personne à franchir la ligne d'arrivée peut être accomplie en interagissant avec les valeurs d'origine:

>>>

>>> every_thirtyseventh_runners = runners[::37]

every_thirtyseventh_runners est créé en utilisant une foulée dans la syntaxe des tranches de liste surrunners, qui contient toujours l'ordre d'origine dans lequel les coureurs ont franchi la ligne d'arrivée.

Comment trier en Python: Conclusion

.sort() etsorted() peuvent fournir exactement l'ordre de tri dont vous avez besoin si vous les utilisez correctement avec les arguments de mot-clé optionnelsreverse etkey.

Les deux ont des caractéristiques très différentes en ce qui concerne la sortie et les modifications sur place, alors assurez-vous de réfléchir à toute fonctionnalité d'application ou à tout programme qui utilisera.sort() car il peut irrévocablement écraser les données.

Pour les Pythonistes passionnés à la recherche d'un défi avec le tri, essayez d'utiliser des types de données plus complexes dans le tri: les itérables imbriqués. N'hésitez pas non plus à vous plonger dans les implémentations de code Python open source pour les composants intégrés et à lire sur l'algorithme de tri utilisé dans Python appeléTimsort.