IdentifiantMot de passe
Loading...
Mot de passe oublié ?Je m'inscris ! (gratuit)
Navigation

Inscrivez-vous gratuitement
pour pouvoir participer, suivre les réponses en temps réel, voter pour les messages, poser vos propres questions et recevoir la newsletter

Python Discussion :

Tri d'une liste [Python 3.X]


Sujet :

Python

  1. #1
    Membre habitué
    Homme Profil pro
    développeur occasionnel
    Inscrit en
    Octobre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : développeur occasionnel

    Informations forums :
    Inscription : Octobre 2015
    Messages : 10
    Par défaut Tri d'une liste
    Bonjour,
    Je suis en train de passer mon programme de 2.7 à 3.5
    Les instances de ma liste sont des fichiers généalogiques de la forme suivante:
    o_durand_alain_1666.png
    Mon objectif est de faire un tri sur les dates.
    Mon script comprend donc:

    lambda v1:v2
    print(liste0.sort(liste0,key=lambda v1[-8:-4]:v2[-8:-4]))

    Cela ne marche pas: on me répond que la syntaxe est incorrecte.:(
    Quelqu'un peut-il m'aider?
    Merci d'avance
    J.

  2. #2
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    key sert à désigner quel élément doit être pris comme base de la comparaison pour le tri. Donc, il rentre l'élément de la liste "o_durand_alain_1666.png", et on doit prendre "o_durand_alain_1666.png"[-8:-4] => 1666. Cela donne comme argument lambda v: v[-8:-4]:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    liste0.sort(key=lambda v:v[-8:-4])
    print(liste0)
    La méthode .sort(...) modifie la liste "sur place" mais ne renvoie rien. Pour créer une nouvelle liste sans modifier list0, on peut utiliser la fonction sorted:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    print(sorted(liste0, key=lambda v:v[-8:-4])

  3. #3
    Membre habitué
    Homme Profil pro
    développeur occasionnel
    Inscrit en
    Octobre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : développeur occasionnel

    Informations forums :
    Inscription : Octobre 2015
    Messages : 10
    Par défaut Tri d'une liste
    Cela marche. Merci et bonne journée
    J

  4. #4
    Membre habitué
    Homme Profil pro
    développeur occasionnel
    Inscrit en
    Octobre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : développeur occasionnel

    Informations forums :
    Inscription : Octobre 2015
    Messages : 10
    Par défaut Tri Python selon plusieurs critères
    Je cherche à trier la liste ci-dessus selon 2 critères:
    - critère principal: le nom (3eme caractère)
    - critère secondaire: l'année

    J'ai essayé la fonction suivante, évidemment sans succès:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    def compare(v1, v2):
        if v1[2]<v2[2]:
            return -1
        elif v1[-8:-4]>v2[-8:-4]:
            return 1
        else:
            return 0
    print(liste.sort(compare()))
    Il y a sûrement mieux
    Merci d'avance
    J

  5. #5
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    En plus d'être rapide, la fonction de tri de Python est "stable", ce qui veut dire que l'ordre des éléments égaux de la liste à trier est conservé. On peut donc chainer les tris pour faire du tri multicritères:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    liste = [
    "o_durand2_alain_1666.png",
    "o_durand1_alain_1665.png",
    "o_durand2_alain_1662.png",
    "o_durand4_alain_1669.png",
    "o_durand2_alain_1667.png",
    "o_durand1_alain_1668.png"
    ]
    Version avec la fonction sorted (ne change pas la liste initiale):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    liste2 = sorted(liste, key=lambda v:v.split('_')[3])
    liste3 = sorted(liste2, key=lambda v:v.split('_')[1])
    for x in liste3:
        print(x)
    Version avec la méthode sort (tri sur place):

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    liste.sort(key=lambda v:v.split('_')[3])
    liste.sort(key=lambda v:v.split('_')[1])
    for x in liste:
        print(x)
    On peut aussi trier une sous-liste:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    liste2 = sorted(liste, key=lambda v: [v.split('_')[1], v.split('_')[3]])
    for x in liste2:
        print(x)
    Les 3 solutions donnant, bien sûr, le même résultat:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    o_durand1_alain_1665.png
    o_durand1_alain_1668.png
    o_durand2_alain_1662.png
    o_durand2_alain_1666.png
    o_durand2_alain_1667.png
    o_durand4_alain_1669.png

  6. #6
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Salut,

    multicritère, c'est aussi: sorted(liste, key=lambda s: (s[2], s[-8:-4])) i.e. la liste est triée en comparant les tuple (s[2], s[-8:-4]) suivant l'ordre alphabétique.

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  7. #7
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    En ce qui concerne les tris, et bien que les codes proposés plus haut soient corrects, il faut se méfier ici de 2 choses:

    - on parle de "tri sur les dates" et les dates sont représentées par "1666". Si ces dates sont en fait les nombres de jours qui suivent une date donnée, il faut faire des tris entre les NOMBRES et non les chaines! Sur cet exemple, on voit bien la différence entre les 2:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    print(sorted([5,9,10,15]))
    [5, 9, 10, 15]
    print(sorted(["5","9","10","15"]))
    ['10', '15', '5', '9']
    - on parle aussi de "tri sur les noms" de personnes. Mais les noms peuvent être mélangés en majuscules/minuscules, et ils peuvent avoir des accents. Or, les fonctions de tri fonctionnent avec l'ordre de type ASCII, c'est à dire que les minuscules sont APRES les majuscules:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print(sorted(["Xavier", "alain"]))
    ['Xavier', 'alain']
    Pour retrouver un classement correct, il suffit de demander à ce que le tri se fasse après avoir demandé le passage en majuscule (.upper()).

    Et pour les caractères accentués, c'est pire puisqu'ils sont APRES toutes les minuscules. Donc, "é" se trouve APRES "x":

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    print(sorted(["é", "x"]))
    ['x', 'é']
    Si le problème se pose avec les caractères accentués, il faut créer une fonction particulière pour que le tri se fasse correctement selon le dictionnaire français par exemple.

  8. #8
    Membre habitué
    Homme Profil pro
    développeur occasionnel
    Inscrit en
    Octobre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : développeur occasionnel

    Informations forums :
    Inscription : Octobre 2015
    Messages : 10
    Par défaut Tri Python selon plusieurs critères
    Merci à tous les deux de votre aide et de ces rappels bien utiles après avoir laissé dormir ce script pendant presque 5 ans
    Les 2 formules marchent bien sûr mais j'ai privilégié la seconde, plus légère, l'un des objectifs de la réécriture étant de faire maigrir le code d'au moins 30%.
    Je m'interroge cependant sur la perfection du tri python: ce n'est pas la première fois que je le vois mais vous pouvez aussi constater que l'ordre alphabétique n'est pas intégralement respecté dans ce tableau:
    http://www.liversay.free.fr/44/html/mariages.php
    Est-ce mon code (tri sur un seul caractère?)? Est-ce la disposition en tableau?
    Qu'en pensez-vous?
    J

  9. #9
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Bonjour,

    Citation Envoyé par Nordier Voir le message
    Je m'interroge cependant sur la perfection du tri python
    Le tri Python marche très bien!

    Citation Envoyé par Nordier Voir le message
    Est-ce mon code (tri sur un seul caractère?)?
    Sans aucun doute: Python n'a fait que le tri demandé.

    Citation Envoyé par Nordier Voir le message
    Est-ce la disposition en tableau?
    Non.

    Si tu veux le tri en une seule ligne, et compte tenu de mon message précédent (à relire), voilà ma dernière proposition:

    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    6
    7
    8
    9
    10
    11
    12
    13
    14
    15
    16
    17
    18
    19
    20
    liste = [
    "o_durand2_alain_1666.png",
    "o_durand1_alain_1665.png",
    "o_durand2_alain_1662.png",
    "o_durand4_alain_1669.png",
    "o_durand2_alain_1667.png",
    "o_durand1_alain_1668.png"
    ]
     
    liste2 = sorted(liste, key=lambda v: [v.split('_')[1].upper(), int(v.split('_')[3].split('.')[0])])
     
    for x in liste2:
        print(x)
     
    o_durand1_alain_1665.png
    o_durand1_alain_1668.png
    o_durand2_alain_1662.png
    o_durand2_alain_1666.png
    o_durand2_alain_1667.png
    o_durand4_alain_1669.png
    Explication pour v.split('_')[1].upper():
    La formule découpe la chaine avec '_', en prend la sous-chaine d'indice 1 (="nom"), et passe ce nom en majuscule avec upper

    Explication pour int(v.split('_')[3].split('.')[0]):
    La formule découpe la chaine avec '_', en prend la sous-chaine d'indice 3 (="date.png"), le redécoupe avec '.', en prend la sous-chaine d'indice 0 (="date"), et la passe en entier avec int.

    Cela suppose, bien sûr, que toutes les chaines à trier ont la même structure avec les '_' comme séparateurs.

  10. #10
    Membre habitué
    Homme Profil pro
    développeur occasionnel
    Inscrit en
    Octobre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : développeur occasionnel

    Informations forums :
    Inscription : Octobre 2015
    Messages : 10
    Par défaut Tri Python selon plusieurs critères
    Après plusieurs essais suite à erreurs de syntaxe (notamment upper rejeté), j'ai retenu la formule suivante:
    Code : Sélectionner tout - Visualiser dans une fenêtre à part
    1
    2
    3
    4
    5
    #liste44ab=sorted(liste44a,key=lambda v:(v[2],v[-8:-4]))                    #liste44 triée sur le 3eme caractère, puis sur l'année
    #liste44d=sorted(liste44,key=lambda v:(v[-8:-4],v[2]))                      # liste triée sur les dates, puis sur le nom, avec chemins complets
    liste44ab=sorted(liste44a, key=lambda v: [v.split('_')[2], v.split('_')[-8:-4]])
    liste44d=sorted(liste44a, key=lambda v: [v.split('_')[-8:-4], v.split('_')[2]])
    #liste2 = sorted(liste, key=lambda v: [v.split('_')[1].upper(), int(v.split('_')[3].split('.')[0])])
    Désolé, cela ne marche pas. Aucun tri.

  11. #11
    Expert éminent
    Homme Profil pro
    Architecte technique retraité
    Inscrit en
    Juin 2008
    Messages
    21 754
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Manche (Basse Normandie)

    Informations professionnelles :
    Activité : Architecte technique retraité
    Secteur : Industrie

    Informations forums :
    Inscription : Juin 2008
    Messages : 21 754
    Par défaut
    Citation Envoyé par Nordier Voir le message
    Désolé, cela ne marche pas. Aucun tri.
    Sans doute que vos noms ne contiennent pas un nombre constant de '_'.
    Essayez avec sorted(liste, key=lambda s: (s[2:-9].upper(), s[-8:-4])).

    - W
    Architectures post-modernes.
    Python sur DVP c'est aussi des FAQs, des cours et tutoriels

  12. #12
    Expert confirmé
    Avatar de tyrtamos
    Homme Profil pro
    Retraité
    Inscrit en
    Décembre 2007
    Messages
    4 486
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Var (Provence Alpes Côte d'Azur)

    Informations professionnelles :
    Activité : Retraité

    Informations forums :
    Inscription : Décembre 2007
    Messages : 4 486
    Billets dans le blog
    6
    Par défaut
    Je ne vois pas comment "upper" peut-être rejeté puisqu'il existait déjà avec Python 2. Un petit coup d’œil dans la doc => https://docs.python.org/3/library/st...pper#str.upper.

    Et j'ai bien testé mon code avant de le publier...

    Il ne reste qu'à vérifier sous quelles formes se trouvent les éléments de la liste à trier. On ne peut pas tout deviner.

  13. #13
    Membre habitué
    Homme Profil pro
    développeur occasionnel
    Inscrit en
    Octobre 2015
    Messages
    10
    Détails du profil
    Informations personnelles :
    Sexe : Homme
    Localisation : France, Charente Maritime (Poitou Charente)

    Informations professionnelles :
    Activité : développeur occasionnel

    Informations forums :
    Inscription : Octobre 2015
    Messages : 10
    Par défaut Tri Python selon plusieurs critères
    Sans doute que vos noms ne contiennent pas un nombre constant de '_'.
    Essayez avec sorted(liste, key=lambda s: (s[2:-9].upper(), s[-8:-4])).
    C'est exact. c'est sans doute là la cause profonde de mon problème. Il y a en effet quelques exceptions que je ne peux lever, liées à la nature du nom.
    Cette formule permet de lever toutes les imprécisions du tri qui est maintenant parfait:
    http://www.liversay.free.fr/44/html/baptemes.php
    Merci.
    Merci à tous les deux pour votre aide.
    J

+ Répondre à la discussion
Cette discussion est résolue.

Discussions similaires

  1. [SQL] Tri d'une liste!!!
    Par frutix dans le forum PHP & Base de données
    Réponses: 3
    Dernier message: 03/02/2006, 10h00
  2. [Requête] Tri via une liste déroulante
    Par Burnout dans le forum Requêtes et SQL.
    Réponses: 4
    Dernier message: 09/01/2006, 18h16
  3. Tri d'une liste d'objet CObList
    Par cjacquel dans le forum MFC
    Réponses: 1
    Dernier message: 13/07/2005, 13h50
  4. [TRI] tri d'une list provenant de LabelValueBean
    Par Canou dans le forum Struts 1
    Réponses: 6
    Dernier message: 20/09/2004, 14h55
  5. tri d'une liste
    Par Guigui_ dans le forum Langage
    Réponses: 4
    Dernier message: 09/01/2003, 18h08

Partager

Partager
  • Envoyer la discussion sur Viadeo
  • Envoyer la discussion sur Twitter
  • Envoyer la discussion sur Google
  • Envoyer la discussion sur Facebook
  • Envoyer la discussion sur Digg
  • Envoyer la discussion sur Delicious
  • Envoyer la discussion sur MySpace
  • Envoyer la discussion sur Yahoo