Ranger une liste de tuples
Résolu/Fermé
Pirate91gb
-
Modifié le 26 avril 2021 à 10:27
mamiemando Messages postés 33367 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 19 novembre 2024 - 27 avril 2021 à 14:05
mamiemando Messages postés 33367 Date d'inscription jeudi 12 mai 2005 Statut Modérateur Dernière intervention 19 novembre 2024 - 27 avril 2021 à 14:05
A voir également:
- Ranger une liste de tuples
- Liste déroulante excel - Guide
- Liste déroulante en cascade - Guide
- Liste de diffusion whatsapp - Guide
- Ranger par ordre alphabétique excel - Guide
- Gertrude a préparé la liste des affaires à prendre pour l'excursion. juliette a modifié cette liste en utilisant le mode suivi des modifications proposé par le traitement de texte. - Guide
4 réponses
yg_be
Messages postés
23342
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
21 novembre 2024
Ambassadeur
1 551
26 avril 2021 à 10:44
26 avril 2021 à 10:44
bonjour,
par exemple:
par exemple:
liste.sort(key= lambda x : x[2])
mamiemando
Messages postés
33367
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
19 novembre 2024
7 801
26 avril 2021 à 14:09
26 avril 2021 à 14:09
Bonjour,
Explications préliminaires
Par défaut, les éléments itérables et indexés (e.g.
Exemple : dans cet exemple,
Contrairement à d'autre langages, la fonction
Le choix qui a été fait dans python c'est qu'on utilise toujours
Conséquences
Exemple : Ici chaque tuple (entier, caractère) et converti sous la forme (caractère, entier) et donc on trie en priorité sur la partie caractère et si ça ne suffit pas sur la partie entière.
Exemple : Ici on trie selon (-entier, caractère) donc on trie selon la partie entière dans l'ordre décroissant, et si ça ne suffit pas, selon la partie caractère
Retour à ton cas
Dans ton cas tu sembles trier les tuples en ignorant le premier élément (la partie chaîne), puis selon l'ordre lexicographique en comparant d'abord le second élément et si besoin le troisième élément. Ce qui donne :
Bonne chance
Explications préliminaires
Par défaut, les éléments itérables et indexés (e.g.
listet
tuple) exposent l'opérateur
<de sorte à implémenter un ordre lexicographique :
- on prend le premier élément des deux tuples comparés
- si l'un est plus petit il permet de d'élire le plus petit élément
- sinon on passe au second élément et ainsi de suite, jusqu'à élire un plus petit élément.
Exemple : dans cet exemple,
sortcompare d'abord la partie entière des tuples, et si ça ne suffit pas on regarde la partie caractère :
l = [(1,'b'), (2, 'a'), (1, 'a'), (0, 'z')] l.sort() print(l) #[(0, 'z'), (1, 'a'), (1, 'b'), (2, 'a')]
Contrairement à d'autre langages, la fonction
sortedde python (ou la méthode
list.sort), il n'est pas possible de passer en paramètre la relation d'ordre
<de son choix, ce qui signifie qu'on pourrait croire qu'on est bloqué si le comportement par défaut de
<n'est pas celui escompté.
Le choix qui a été fait dans python c'est qu'on utilise toujours
<quitte à convertir l'élément de la liste à trier par une représentation sur laquelle
<fera ce qu'il faut.
Conséquences
- Si les éléments de ta liste sont des tuples/listes tel qu'ils doivent être ordonnés autrement que selon l'ordre lexicographique, il faut passer en paramètre la callback key adéquate.
- Si tu tries une liste de tuples et que ces tuples ne sont pas triés selon l'ordre lexicographique (e.g. comparer le 2e attribut puis le 1er), la callback
key
doit les mettre dans le bon ordre.
Exemple : Ici chaque tuple (entier, caractère) et converti sous la forme (caractère, entier) et donc on trie en priorité sur la partie caractère et si ça ne suffit pas sur la partie entière.
l = [(1,'b'), (2, 'a'), (1, 'a'), (0, 'z')] l.sort(key=lambda tup: (tup[1], tup[0])) print(l) #[(1, 'a'), (2, 'a'), (1, 'b'), (0, 'z')]
- Si l'un des attributs confronté ne doit pas être trié selon <, mais selon une autre relation d'ordre (e.g. >), charge à la callback key d'adapter la représentation en conséquence. Par exemple en prenant la valeur opposée.
Exemple : Ici on trie selon (-entier, caractère) donc on trie selon la partie entière dans l'ordre décroissant, et si ça ne suffit pas, selon la partie caractère
l = [(1,'b'), (2, 'a'), (1, 'a'), (0, 'z')] l.sort(key=lambda tup: (-tup[0], tup[1]) print(l) #[(2, 'a'), (1, 'a'), (1, 'b'), (0, 'z')]
- Si une partie des éléments à trier n'est pas pertinente, il suffit de l'omettre dans la valeur retournée par la callback
key
(c'est la solution proposée par yg_be : il ne fait la comparaison que sur le troisième attribut du tuple).
Retour à ton cas
Dans ton cas tu sembles trier les tuples en ignorant le premier élément (la partie chaîne), puis selon l'ordre lexicographique en comparant d'abord le second élément et si besoin le troisième élément. Ce qui donne :
tab = [ ["Bleu", 2, 3], ["Orange", 1, 5], ["Vert", 2, 4], ["Rose", 1, 3] ] tab.sort(key=lambda tup: (tup[1], tup[2])) print(tab) #[['Rose', 1, 3], ['Orange', 1, 5], ['Bleu', 2, 3], ['Vert', 2, 4]]
Bonne chance
yg_be
Messages postés
23342
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
21 novembre 2024
1 551
Modifié le 26 avril 2021 à 14:45
Modifié le 26 avril 2021 à 14:45
En Python, la fonction sorted de python (ou la méthode list.sort) permet de passer en paramètre la relation d'ordre < de son choix, exemple:
plus compact:
import functools def jecompare (a,b): if a[1]<b[1]: return(-1) elif a[1]>b[1]: return(1) elif a[2]<b[2]: return(-1) elif a[2]>b[2]: return(1) else: return(0) tab = [["Bleu",2,3],["Orange",1,5],["Vert",2,4],["Rose",1,3]] print(tab) tab.sort(key=functools.cmp_to_key(jecompare)) print(tab)
plus compact:
def jecompare (a,b): if a[1]!=b[1]: return(a[1]-b[1]) else: return(a[2]-b[2])
mamiemando
Messages postés
33367
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
19 novembre 2024
7 801
>
yg_be
Messages postés
23342
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
21 novembre 2024
Modifié le 29 avril 2021 à 16:18
Modifié le 29 avril 2021 à 16:18
Intéressant je ne connaissais pas
Ceci dit ce n'est pas exactement ce que j'entendais dans mon message précédent. Si tu prends un préordre (donc une relation qui prend en paramètre deux éléments et retourne un booléen), tu ne pourras pas directement utiliser
En effet,
Cela signifie que si tu définis un préordre sur un objet
cmp_to_key, merci :-)
Ceci dit ce n'est pas exactement ce que j'entendais dans mon message précédent. Si tu prends un préordre (donc une relation qui prend en paramètre deux éléments et retourne un booléen), tu ne pourras pas directement utiliser
functools.cmp_to_key.
En effet,
cmp_to_keyattend que la fonction enveloppée retourne un entier et prend une décision en fonction de son signe, comme le montre son implémentation :
def cmp_to_key(mycmp): """Convert a cmp= function into a key= function""" class K(object): __slots__ = ['obj'] def __init__(self, obj): self.obj = obj def __lt__(self, other): return mycmp(self.obj, other.obj) < 0 def __gt__(self, other): return mycmp(self.obj, other.obj) > 0 def __eq__(self, other): return mycmp(self.obj, other.obj) == 0 def __le__(self, other): return mycmp(self.obj, other.obj) <= 0 def __ge__(self, other): return mycmp(self.obj, other.obj) >= 0 __hash__ = None return K
Cela signifie que si tu définis un préordre sur un objet
Toto(sous-entendu qui n'est pas
Toto.__lt__)
cmp_to_keyne répond pas exactement à la question. Il va falloir au préalable avoir recours à adapter le pré-ordre pour que sa valeur de retour soit une valeur signée (comme le montre la fonction
preorder_to_cmpdans l'exemple ci-dessous) :
#!/usr/bin/env python3 from functools import cmp_to_key, partial def my_preorder(a, b): return a >= b def preorder_to_cmp(a, b, preorder=None): return ( -1 if preorder(a, b) else 1 if preorder(b, a) else 0 ) l = [1, 3, 4, 2] l.sort(key=cmp_to_key(partial(preorder_to_cmp, preorder=my_preorder))) print(l) # [4, 3, 2, 1]
Bonjour,
Merci, de plus j'aimerais (je ne l'ai pas précisé avant) trié un tableau comme celui ci
Merci, de plus j'aimerais (je ne l'ai pas précisé avant) trié un tableau comme celui ci
tab = [["Bleu",2,3],["Orange",1,5],["Vert",2,4],["Rose",1,3]]en
tab= [["Rose",1,3],["Orange",1,5],["Bleu",2,3],["Vert",2,4]]. La différence est que tab[i][2] est comparé avec tab[i+1][2] quand tab[i][1] et tab[i+1][1] sont égaux.
yg_be
Messages postés
23342
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
21 novembre 2024
1 551
26 avril 2021 à 12:45
26 avril 2021 à 12:45
as-tu essayé:
tab.sort(key= lambda x : (x[1],x[2]))
Bonjour,
je te remercie pour toute l'aide et les explications (meilleures que mon prof) sur les fonctions de rangement.
Cordialement
je te remercie pour toute l'aide et les explications (meilleures que mon prof) sur les fonctions de rangement.
Cordialement
yg_be
Messages postés
23342
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
21 novembre 2024
1 551
26 avril 2021 à 15:15
26 avril 2021 à 15:15
peux-tu alors marquer la discussion comme résolue?
mamiemando
Messages postés
33367
Date d'inscription
jeudi 12 mai 2005
Statut
Modérateur
Dernière intervention
19 novembre 2024
7 801
>
yg_be
Messages postés
23342
Date d'inscription
lundi 9 juin 2008
Statut
Contributeur
Dernière intervention
21 novembre 2024
27 avril 2021 à 14:05
27 avril 2021 à 14:05
Comme son compte n'est pas enregistré, je ne pense pas qu'il puisse le faire, je m'en occupe. Bonne journée à vous deux.