Contenu | Rechercher | Menus

Annonce

Si vous avez des soucis pour rester connecté, déconnectez-vous puis reconnectez-vous depuis ce lien en cochant la case
Me connecter automatiquement lors de mes prochaines visites.

À propos de l'équipe du forum.

#1 Le 04/03/2021, à 16:51

chris7522

[RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Bonjour a toutes et a tous ,
Je souhaite trier ma liste et imprimer le nom , prenom ainsi que le plus fort salaire . Est ce que ca se fait  de faire comme ca  ? Aurai-je pu faire plus compacte, plus efficace ?
Merci de votre aide .

liste = [{'n':'berthelot','p':'stephane','s':2500},
         {'n':'sarkosy','p':'nicolas','s':7000},
         {'n':'etchebest','p':'phillipe','s':1250},
         {'n':'rigolo','p':'phillipe','s':4530},
         {'n':'berthelot','p':'jackie','s':2200},
         {'n':'lapin','p':'jeannot'},
         {'n':'jambon','p':'steve','s':5000},
         {'n':'jambon','p':'steven','s':1670}
        ]
        
def tri_dic(liste):
    keys=('s')
    liste.sort(key=lambda d:tuple(d[k] for k in keys if k in d),reverse=True)
    return liste
    
tri_dic(liste)
print(f"Monsieur {liste[0]['n']} {liste[0]['p']} a le plus gros salaire: {liste[0]['s']} Euros")
        
   

Dernière modification par chris7522 (Le 04/03/2021, à 22:17)

Hors ligne

#2 Le 04/03/2021, à 17:23

Vobul

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

chris7522 a écrit :

Aurai-je pu faire plus compacte, plus efficace ?

Sachant que ton code prend une seule ligne, non je crois que ça ne sert à rien de faire plus compact wink


Vobul
Utilisez le retour utilisable de commandes !!!
J'aime la langue française, mais je parle franglais, deal with it.
RTFM

Hors ligne

#3 Le 04/03/2021, à 19:18

pingouinux

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Bonjour,
Tu peux simplifier un peu :

def tri_dic(liste):
    liste.sort(key=lambda d:d['s'] if 's' in d else 0,reverse=True)

Hors ligne

#4 Le 04/03/2021, à 20:35

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Merci beaucoup a tous les deux  smile

pingouinux a écrit :

Bonjour,
Tu peux simplifier un peu :

def tri_dic(liste):
    liste.sort(key=lambda d:d['s'] if 's' in d else 0,reverse=True)

Merci c'est bien plus lisible et agréable !

Hors ligne

#5 Le 04/03/2021, à 21:16

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Bonjour,
remarques:
- tu n'utilises pas le return de ta fonction.
- Il est inutile de renvoyer l'ensemble de la liste alors que c'est juste une information que l'on veut extraire
- J'éviterais de modifier "in place" la liste ...

def tri_dic(liste):
    return sorted(liste,key=lambda d:d['s'] if 's' in d else 0)[-1]
best  = tri_dic(liste)
print(f"Monsieur {best['n']} {best['p']} a le plus gros salaire: {best['s']} Euros")

Note: On ne tient pas compte des éventuelles égalités de salaires

#6 Le 04/03/2021, à 21:54

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Merci de tes remarques .

def tri_dic(liste):
    return sorted(liste,key=lambda d:d['s'] if 's' in d else 0)[-1]

   A quoi sert le [-1] a la fin du return ?
   Peux t on se passer de sort au profit de sorted dans la mesure ou sorted renvoie une copie plutot qu'un tri sur place , a le meme cout mémoire et peut etre utilisé sur n'importe quel itérable ?
   Je vais essayé de réfléchir dans le code aux éventuelles égalités de salaires , c'est pas du tout gagné pour moi !

Dernière modification par chris7522 (Le 04/03/2021, à 22:14)

Hors ligne

#7 Le 05/03/2021, à 00:38

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

chris7522 a écrit :
def tri_dic(liste):
    return sorted(liste,key=lambda d:d['s'] if 's' in d else 0)[-1]

   A quoi sert le [-1] a la fin du return ?

[-1] correspond à un indice de la liste. (lecture de droite à gauche)

>>> l = [0, 1, 2, 3]
>>> l[-1]
3
>>> l[-3]
1
>>> l[0]
0
>>> 
chris7522 a écrit :

   Peux t on se passer de sort au profit de sorted dans la mesure ou sorted renvoie une copie plutot qu'un tri sur place , a le meme cout mémoire et peut etre utilisé sur n'importe quel itérable ?

Tu peux utiliser l'un ou l'autre. Mais je te conseille de travailler sur une copie de ta liste.

copie_liste = liste[:]
copie_liste.sort(...
chris7522 a écrit :

   Je vais essayé de réfléchir dans le code aux éventuelles égalités de salaires , c'est pas du tout gagné pour moi !

Je viens de coder ça. J'attends de voir ton approche...

#8 Le 05/03/2021, à 20:15

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

J'y arrive pas sad
Et ce n'est pas faute d'avoir essayé !

Hors ligne

#9 Le 05/03/2021, à 23:18

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Il a de nombreuse façon de faire...
En restant sur l'idée d'une liste triée en ordre croissant des salaires:

def tri_dic(liste):
    out = []
    listeCopie = liste[:] 
    listeCopie.sort(key=lambda d:d['s'] if 's' in d else 0)
    while True:
        out.append(listeCopie.pop()) 
        if out[0]['s'] != listeCopie[-1]['s']:
            break
    return out


best  = tri_dic(liste)
if len(best)>1:
    print(f"Il y égalité de salaire ({best[0]['s']} euros) avec {len(best)} \
personnes:")
    for dic in best:
          print(f"{dic['n']} {dic['p']}")
else:
    print(f"Monsieur {best[0]['n']} {best[0]['p']} a le plus gros salaire:\
{best[0]['s']} Euros")

Dernière modification par Compte supprimé (Le 05/03/2021, à 23:19)

#10 Le 06/03/2021, à 12:29

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Parfait smile
Mille Merci .
Cependant , cette instruction n'est pas claire pour moi :

out.append(listeCopie.pop()) 

J'ajoute a ma liste out , mais ensuite ...
Peux tu s'il te plait , me l'expliquer dans le détail ?

Hors ligne

#11 Le 06/03/2021, à 14:48

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

while True:
        out.append(listeCopie.pop()) #je prends le dernier élément de listeCopie que je "déplace" dans la liste out. (Vu que la listecopie a été trié selon le salaire par ordre croissant, cet élèment correspond donc au meilleur salaire) 
        if out[0]['s'] != listeCopie[-1]['s']: #si le meilleur salaire trouvé est différent du salaire suivant, c'est qu'il n'y personne d'autre qui bénéficie du même salaire et donc on quitte la boucle et on retourne le résultat. Si équivalence, c'est qu'il y a un autre prétendant au trône du meilleur salaire et donc on reste dans la boucle...
            break
    return out

J'espère que mes commentaires sont assez explicites. (Sinon je développerai d'avantage wink)

#12 Le 07/03/2021, à 11:56

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Très explicite ! Merci
Une derniere chose :

listeCopie.sort(key=lambda d:d['s'] if 's' in d else 0)

Pourquoi le  'else 0 ' ( particulierement le 0 ) est utile , ou meme obligatoire dans le cas présent , a quoi sert il ? On me l'a deja expliqué mais j'ai déja oublié .

Hors ligne

#13 Le 07/03/2021, à 12:31

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

...Il est utile que si la clef 's' du dico est absente. Comme c'est le cas avec la liste que tu nous as proposé.

chris a écrit :

liste = [{'n':'berthelot','p':'stephane','s':2500},
         {'n':'sarkosy','p':'nicolas','s':7000},
         {'n':'etchebest','p':'phillipe','s':1250},
         {'n':'rigolo','p':'phillipe','s':4530},
         {'n':'berthelot','p':'jackie','s':2200},
        {'n':'lapin','p':'jeannot'},
         {'n':'jambon','p':'steve','s':5000},
         {'n':'jambon','p':'steven','s':1670}
        ]

#14 Le 07/03/2021, à 12:35

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Si toutes les clefs 's' sont présentes, tu peux faire simplement:

listeCopie.sort(key=lambda d:d['s'] )

#15 Le 07/03/2021, à 12:56

pingouinux

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

pseudofab #14 a écrit :

Si toutes les clefs 's' sont présentes, tu peux faire simplement:

listeCopie.sort(key=lambda d:d['s'] )

Non, c'est une erreur de syntaxe, et le else est obligatoire. L'erreur apparaît avant même de lire la liste.

Hors ligne

#16 Le 07/03/2021, à 13:05

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

pingouinux a écrit :
pseudofab #14 a écrit :

Si toutes les clefs 's' sont présentes, tu peux faire simplement:

listeCopie.sort(key=lambda d:d['s'] )

Non, c'est une erreur de syntaxe, et le else est obligatoire. L'erreur apparaît avant même de lire la liste.

>>> liste = [{'n':'berthelot','p':'stephane','s':2500},
         {'n':'sarkosy','p':'nicolas','s':7000},
         {'n':'etchebest','p':'phillipe','s':1250},
         {'n':'rigolo','p':'phillipe','s':4530},
         {'n':'berthelot','p':'jackie','s':2200},
	 {'n':'jambon','p':'steve','s':5000},
         {'n':'jambon','p':'steven','s':1670}
        ]
>>> liste.sort(key=lambda d:d['s'] )
>>> liste
[{'n': 'etchebest', 'p': 'phillipe', 's': 1250}, {'n': 'jambon', 'p': 'steven', 's': 1670}, {'n': 'berthelot', 'p': 'jackie', 's': 2200}, {'n': 'berthelot', 'p': 'stephane', 's': 2500}, {'n': 'rigolo', 'p': 'phillipe', 's': 4530}, {'n': 'jambon', 'p': 'steve', 's': 5000}, {'n': 'sarkosy', 'p': 'nicolas', 's': 7000}]
>>> 

#17 Le 07/03/2021, à 15:07

pingouinux

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

@pseudofab #16 : Au temps pour moi, tu as raison. J'avais testé avec la seconde ligne.

liste.sort(key=lambda d:d['s'])                    # Ça marche
liste.sort(key=lambda d:d['s'] if 's' in d)        # Ça ne marche pas
liste.sort(key=lambda d:d['s'] if 's' in d else 0) # Ça marche

Hors ligne

#18 Le 07/03/2021, à 15:26

beuguissime

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Bonjour,

Sinon, pour éviter un if :

d.get('s', 0)

Hors ligne

#19 Le 07/03/2021, à 15:30

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

@pingouinux: ça me rassure de savoir que tu veilles aux grains wink

liste.sort(key=lambda d:d['s'] if 's' in d)

Effectivement ceci est incorrect: Il faut bien dire à python comment se comporter dans le cas où la clef est absente...

Dernière modification par Compte supprimé (Le 07/03/2021, à 15:32)

#20 Le 07/03/2021, à 15:48

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

beuguissime a écrit :

Bonjour,

Sinon, pour éviter un if :

d.get('s', 0)

Bonjour @beuguissime,
+1
C'est ce qui faut conseiller/utiliser wink

#21 Le 07/03/2021, à 19:51

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Merci pour toutes ces précisions smile
Bonne semaine

Hors ligne

#22 Le 08/03/2021, à 09:56

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Dans la continuité, si tu as envie, je te propose l'exercice suivant :
Soit la liste:

l = [{'n':'dupont','p':'stephane','s':2500},
	 {'n':'dubois','p':'nicolas','s':7000},
         {'n':'ducon','p':'phillipe','s':1250},
         {'n':'ducon','p':'alice','s':4530},
         {'n':'dupont','p':'jackie','s':2200},
         {'n':'lapin','p':'jeannot'},
         {'n':'dubois','p':'fanny','s':5000},
         {'n':'dupont','p':'steven','s':1670},
	 {'n':'durant', 'p':'fabienne', 's':550},
	 {'n':'durant', 'p':'eric', 's':1300}]

Créer une fonction qui prend pour argument la liste et qui retourne:
          --> le nom de la famille qui gagne le plus.
          --> le nom de la famille qui gagne le moins.

#23 Le 08/03/2021, à 13:06

Compte supprimé

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Je viens de réaliser l'exercice que je t'ai soumis (ben oui je te propose un truc que moi-même n'avais pas essayé).
C'est peut-être un peu complexe pour toi à réaliser au niveau de l'algo (au niveau de tes connaissances python pas de souci wink ).
Si tu veux t'y essayer, retourne juste le nom de la famille qui gagne le plus.

#24 Le 09/03/2021, à 17:28

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

je suis sur le point de sortir quelque chose mais je m'embrouille un peu smile
Laisse moi encore réflechir un peu

Dernière modification par chris7522 (Le 09/03/2021, à 17:29)

Hors ligne

#25 Le 09/03/2021, à 19:39

chris7522

Re : [RESOLU]Tri d'une liste de dictionnaires avec lambda et compréhension

Ne serait il pas possible dans un premier temps de supprimer le dictionnaire qui ne contient pas de salaire .
  Ensuite faire le tri croissant .
  Une fois la liste triée,  récupérer le premier élément ([0]) pour connaître le nom de famille qui gagne le moins, et le dernier élément ([-1]) pour la famille qui gagne le plus.
   un truc comme ca :
 

def tri_dic(liste):
    liste_trie = liste.sorted((d for d in liste if 's' in d),key=lambda d:d['s'])
    return liste_trie
    
liste_trie = tri_dic(liste)
print(f"La famille qui gagne le moins :{liste_trie[0]['n']},La famille qui gagne le plus :{liste_trie[-1]['n']}")	

Hors ligne