Trier suivant un critère☘
Dans la page précédente, nous avons trier suivant un critère "naturel": l'ordre usuel sur les nombres.
Mais il est tout à fait possible de trier suivant d'autres critères.
Exemple☘
On dispose d'une liste d'entiers naturels:
L = [ 12, 67, 32, 434, 531, 10, 100]
On aimerait les ranger dans l'ordre croissant du chiffre des unités. Pour cela, il suffit de préciser une clef avec la syntaxe suivante:
def unite(entier):
"""
entier est un entier naturel.
renvoie le chiffre des unités de entier (en base dix)
"""
return entier%10
L = [ 12, 67, 32, 434, 531, 10, 100]
L.sort(key=unite)
Après ces lignes, la valeur de L est [10, 100, 531, 12, 32, 434, 67]
.
Que s'est-il passé ?
Python a associé à chaque élément de la liste son image par la fonction unite
puis a rangé les éléments de la liste suivant l'ordre croissant de ces images par la fonction unite
.
Exercice☘
Trier la liste précédente suivant l'ordre décroissant du chiffre des unités.
Solution
Il suffit d'utiliser reverse=True
.
def unite(entier):
"""
entier est un entier naturel.
renvoie le chiffre des unités de entier (en base dix)
"""
return entier%10
L = [ 12, 67, 32, 434, 531, 10, 100]
L.sort(key=unite, reverse=True)
Tri suivant le chiffre des dizaines☘
Ecrire une fonction prenant en paramètre une liste d'entiers naturels et renvoyant en sortie une liste triée suivant l'ordre croissant du chiffre des dizaines (sans effet de bord sur la liste donnée en argument: elle doit rester intacte).
Chiffre des dizaines
Avec de l'arithmétique élémentaire:
def dizaine(entier):
"""
entier est un entier naturel.
renvoie le chiffre des dizaines de entier (en base dix)
"""
nb_dizaines = entier//10 # le nombre de dizaines
chiffre_dizaine = nb_dizaines%10 # le chiffre des dizaines
return chiffre_dizaine
Avec une astuce du langage Python:
def dizaine(entier):
"""
entier est un entier naturel.
renvoie le chiffre des dizaines de entier (en base dix)
"""
return int(str(entier)[-2])
On a d'abord tranformé l'entier en chaîne avec str(entier)
puis récupéré l'avant dernier caractère avec str(entier)[-2]
et enfin transformé ce caractère en entier avec int
.
le tri
Comme on veut éviter les effets de bord sur la liste, on utilisera sorted
plutôt que sort
.
def dizaine(entier):
"""
entier est un entier naturel.
renvoie le chiffre des dizaines de entier (en base dix)
"""
nb_dizaines = entier//10 # le nombre de dizaines
chiffre_dizaine = nb_dizaines%10 # le chiffre des dizaines
return chiffre_dizaine
def tri_suivant_dizaine(tab):
"""
tab est une liste d'entiers naturels
renvoie la liste triée suivant l'ordre croissant du chiffre des dizaines
"""
return sorted(tab, key=dizaine)
Exemple d'appel:
>>> L = [ 12, 67, 32, 434, 531, 10, 100]
>>> tri_suivant_dizaine(L)
[100, 12, 10, 32, 434, 531, 67]
Tri stable☘
Le tri en langage python est dit stable, ce qui signifie que deux éléments indiscernables par le critère de tri choisi sont laissés dans le même ordre que la liste de départ.
Exemple.
Dans l'illustration ci-dessus, nous avons trié la liste L = [ 12, 67, 32, 434, 531, 10, 100]
suivant l'ordre croissant du chiffre des dizaines.
Dans le résultat [100, 12, 10, 32, 434, 531, 67]
, nous constatons que le nombre 12 est situé avant le nombre 10. Pourquoi ?
Solution
Dans la liste initiale L, 12 est situé avant 10. Comme 12 et 10 sont indiscernables suivant le critère choisi (parce qu'ils ont le même chiffre des dizaines), Python les laisse dans la liste finale dans le même ordre que dans la liste initiale (c'est la propriété de stabilité du tri python).
Vous pouvez observer que le résultat du tri de M = [10, 67, 32, 434, 531, 12, 100]
(où l'on a placé 10 avant 12) suivant le même critère (ordre croissant du chiffre des dizaines) donnera une liste où cette fois 10 est avant 12.
Question. Si vous triez maintenant N = [34, 23, 10, 12, 10]
suivant le même critère, qu'obtiendrez-vous ? (essayez de répondre avant de tester).
Solution
On obtient [10, 12, 10, 23, 34]
. 10 et 12 étant indiscernables suivant le critère choisi, on peut obtenir un 10 avant 12 et un 10 après, ils sont conservés dans l'ordre de la liste initiale.
Tri suivant le nombre de chiffres pairs.☘
Trier une liste d'entiers naturels suivant le nombre de chiffres pairs constituant chaque entier.
Par exemple, 214 sera placé après 113 puisque 214 possède deux chiffres pairs tandis que 113 en possède 0. Par contre 124 et 216 sont indiscernables par ce critère (et resteront dans la liste finale dans l'ordre de leur apparition dans la liste initiale).
Nombre de chiffres pairs
On commence par définir une fonction renvoyant le nombre de chiffres pairs d'un entier.
- Avec un peu d'arithmétique. On récupère les chiffres avec l'algorithme des divisions en cascade vu plus tôt dans l'année (à connaître parfaitement, rappelons le) et avec un compteur, on détermine le nombre de chiffres pairs.
def nombre_de_chiffres_pairs(entier):
"""
entier est un entier naturel.
renvoie le nombre de chiffres pairs de l'entier
"""
# on traite le cas de l'entier 0 à part:
if entier == 0: return 1
# cas des entiers > 0:
# initialisation du compteur de chiffres pairs:
compteur = 0
# récupération des chiffres par divisions en cascade:
while entier != 0:
unite = entier%10
if unite%2 == 0:
compteur += 1
entier = entier//10
return compteur
- Avec l'astuce python déjà vue plus haut:
def nombre_de_chiffres_pairs(entier):
"""
entier est un entier naturel.
renvoie le nombre de chiffres pairs de l'entier
"""
return len([c for c in str(entier) if int(c)%2 == 0])
le tri
- Avec
sort
:
def tri_suivant_nb_chiffres_pairs(tab):
"""
tab est une liste d'entiers naturels
trie la liste suivant l'ordre croissant du
nombre de chiffres pairs de chaque entier
"""
tab.sort(key=nombre_de_chiffres_pairs)
- Avec
sorted
:
def tri_suivant_nb_chiffres_pairs(tab):
"""
tab est une liste d'entiers naturels
renvoie une liste, ayant mêmes éléments que tab,
triée suivant l'ordre croissant du
nombre de chiffres pairs de chaque entier.
"""
return sorted(tab, key=nombre_de_chiffres_pairs)
Remarque. Observez la différence dans le choix des mots de la chaîne de documentation. Avec sorted
, la fonction renvoie une liste triée. Avec sort
, la fonction trie la liste.
Pairs d'abord☘
On dispose d'une liste d'entiers naturels. On veut trier cette liste en plaçant les entiers pairs en premier puis les entiers impairs.
Exemple.
Pour la liste L = [3, 22, 5, 6, 10, 7, 5, 4]
le résultat sera [22, 6, 10, 4, 3, 5, 7, 5]
.
Programmez cela.
fonction critère
Quelle fonction définir pour le critère ? On définit une fonction qui associe à chaque entier pair un nombre (par exemple 0) et qui à chaque entier impair associe un autre nombre, plus grand que celui qui est associé aux pairs (par exemple 1).
Le reste modulo 2 convient par exemple:
def reste_modulo2(n):
"""
n est un entier
renvoie le reste modulo 2 de l'entier n
"""
return n%2
Mais on pourrait par exemple utiliser:
def critere(n):
"""
n est un entier
renvoie le reste modulo 2 de l'entier n
"""
if n%2 == 0:
return 42
else:
return 666
le tri
- Avec
sort
:
def pairs_dabord(tab):
"""
tab est une liste d'entiers
trie tab en plaçant les pairs à l'avant
"""
tab.sort(key=reste_modulo2)
- Avec
sorted
:
def pairs_dabord(tab):
"""
tab est une liste d'entiers
renvoie une liste, de mêmes éléments que tab, où les pairs sont placés à l'avant.
"""
return sorted(tab, key=reste_modulo2)