Twitter iPhone pliant OnePlus 11 PS5 Disney+ Orange Livebox Windows 11

Extraire d'un dictionnaire un sous-dictionnaire

21 réponses
Avatar
Olivier Miakinen
Bonjour,

Je cherche Í  résoudre élégamment un problème. Comme souvent j'ai déjÍ 
une idée de la solution, d'o͹ ma question consistant Í  extraire un
sous-dictionnaire d'un dictionnaire. Mais dans un second temps je vais
exposer le vrai problème au cas o͹ mon idée ne serait pas optimale.

====
Voici donc ma question. Supposons que j'ai un dictionnaire, par exemple
mondict = { "t" : "TRUC", "m" : "MACHIN", "b" : "BIDULE", "c" : "CHOSE" }.

J'ai par ailleurs une liste de clés, keys = ["b", "c", "t", "z"], ou un tuple
keys = ("b", "c", "t", "z"), ou un set keys = {"b", "c", "t", "z"}, selon ce
qui sera le plus simple.

Je voudrais, Í  partir de keys (qu'il soit liste, tuple ou set) et de mon
dictionnaire, obtenir un dictionnaire ne contenant que les entrées présentes
dans keys, dans mon exemple "b", "c" et "t", pas l'entrée "m", sans que cela
ne provoque une erreur Í  cause de "z".

Donc :
resultat = { "t" : "TRUC", "b" : "BIDULE", "c" : "CHOSE" }

====
Et maintenant le vrai problème.

Je voudrais appeler une fonction du type :
def lafonction(b=None, c=None, t=None, z=None):
....
en lui passant les valeurs pour b, c, t et z, si elles existent, se trouvant
dans mon dictionnaire mondict. Du coup un truc du genre :
lafonction(**mondict)
mais sans que cela provoque une erreur Í  cause de l'entrée "m".


Cordialement,
--
Olivier Miakinen

10 réponses

1 2 3
Avatar
Olivier Miakinen
Le 25/05/2021 12:04, Nicolas a écrit :
Le dictionnaire en compréhension est moins lisible mais plus concis que
les solutions "éclatées" que j'ai proposées (je sais, certains ne seront
pas d'accord).

Je suis d'accord sur le fait que certains ne seront pas d'accord. ;-)
(et je fais partie de ceux-lÍ )
Et c'est probablement plus rapide aussi.

C'est assez probable. Mais cela dit je me fiche de gagner des poignées de
millisecondes, parce que le traitement que je fais ensuite dure quelques
dizaines de secondes.
--
Olivier Miakinen
Avatar
Olivier Miakinen
Bonjour,
Le 25/05/2021 14:10, Alain Ketterlin m'a répondu :
Je cherche Í  résoudre élégamment un problème. Comme souvent j'ai déjÍ 
une idée de la solution, d'o͹ ma question consistant Í  extraire un
sous-dictionnaire d'un dictionnaire.

Je pense que la solution de Julien est imbattable.

En effet.
Et maintenant le vrai problème.
Je voudrais appeler une fonction du type :
def lafonction(b=None, c=None, t=None, z=None):
....
en lui passant les valeurs pour b, c, t et z, si elles existent, se trouvant
dans mon dictionnaire mondict. Du coup un truc du genre :
lafonction(**mondict)
mais sans que cela provoque une erreur Í  cause de l'entrée "m".

Tu peux aussi ajouter un argument Í  la fonction pour collecter les
déchets :
def lafonction(b=None, c=None, t=None, z=None, **trash):
....
Pas besoin de toucher Í  ton dictionnaire dans ce cas.

C'est vrai, et je garde l'idée pour plus tard si le problème se pose avec
des fonctions que j'aurais écrites moi-même. Mais ici en l'occurrence ce
n'est pas le cas : ce sont des fonctions faisant partie d'une bibliothèque
standard de Python.
Cordialement,
--
Olivier Miakinen
Avatar
Nicolas
Le 25/05/2021 Í  17:28, Olivier Miakinen a écrit :
Bonjour,
Le 25/05/2021 14:10, Alain Ketterlin m'a répondu :
Je cherche Í  résoudre élégamment un problème. Comme souvent j'ai déjÍ 
une idée de la solution, d'o͹ ma question consistant Í  extraire un
sous-dictionnaire d'un dictionnaire.

Je pense que la solution de Julien est imbattable.

En effet.

Il y a deux versions possibles.
Celle de Julien qui itère sur le dictionnaire d'origine :
{key: value for key, value in mondict.items() if key in keys}
et une autre qui itère sur les clés :
{key: mondict[key] for key in keys if key in mon dict}
De façon générale, en fonction de la taille du dictionnaire et de la
taille de la liste de clés, une version peut être plus intéressante que
l'autre. Toujours dans le but de gagner en performance.
Même si ce n'est pas nécessaire ici, tu peux voir les choses autrement :
Le temps CPU non utilisé, c'est de l'énergie économisée.
Nicolas
Avatar
Olivier Miakinen
Le 26/05/2021 14:21, Nicolas a écrit :
Il y a deux versions possibles.
Celle de Julien qui itère sur le dictionnaire d'origine :
{key: value for key, value in mondict.items() if key in keys}
et une autre qui itère sur les clés :
{key: mondict[key] for key in keys if key in mondict}

Les deux sont intéressantes, parce que cela a une incidence sur l'ordre
des clés dans le résultat.
mondict = { "t" : "TRUC", "m" : "MACHIN", "b" : "BIDULE", "c" : "CHOSE" }
keys = ["b", "c", "t", "z"]
{key: value for key, value in mondict.items() if key in keys}
=> {'t': 'TRUC', 'b': 'BIDULE', 'c': 'CHOSE'}
{key: mondict[key] for key in keys if key in mondict}
=> {'b': 'BIDULE', 'c': 'CHOSE', 't': 'TRUC'}
On a bien sÍ»r la même chose si keys est un tuple au lieu d'une liste, mais
l'ordre n'est pas prédictible si c'est un set.
De façon générale, en fonction de la taille du dictionnaire et de la
taille de la liste de clés, une version peut être plus intéressante que
l'autre. Toujours dans le but de gagner en performance.

Dans mon cas, le dictionnaire contiendra généralement trois ou quatre
valeurs, et la liste de clés en contient tout juste cinq : "host",
"port", "user", "password" et "usenetrc". Après avoir fait ce filtrage
une seule fois pour passer les paramètres Í  nntplib.NNTP ou Í 
nntplib.NNTP_SSL, j'utilise le résultat de la connexion pour lire la
totalité de usenet-fr, ce qui me prend en moyenne 45 secondes.
Même si ce n'est pas nécessaire ici, tu peux voir les choses autrement :
Le temps CPU non utilisé, c'est de l'énergie économisée.

Certes. Du coup je pourrais faire une boucle testant un million de fois
chacune des méthodes afin de savoir au finale laquelle est la plus rapide.
Mais avant de rentabiliser l'énergie perdue par mon test il va me falloir
quelques années d'utilisation du programme dÍ»ment optimisé. ;-)
--
Olivier Miakinen
Avatar
rejoc
Ca fait pas le job ??
new_dict = dict((k, v) for k, v in mondict.items() if k in keys)
Le 25/05/2021 00:13, Olivier Miakinen a écrit :
Bonjour,
Je cherche Í  résoudre élégamment un problème. Comme souvent j'ai déjÍ 
une idée de la solution, d'o͹ ma question consistant Í  extraire un
sous-dictionnaire d'un dictionnaire. Mais dans un second temps je vais
exposer le vrai problème au cas o͹ mon idée ne serait pas optimale.
====>
Voici donc ma question. Supposons que j'ai un dictionnaire, par exemple
mondict = { "t" : "TRUC", "m" : "MACHIN", "b" : "BIDULE", "c" : "CHOSE" }.
J'ai par ailleurs une liste de clés, keys = ["b", "c", "t", "z"], ou un tuple
keys = ("b", "c", "t", "z"), ou un set keys = {"b", "c", "t", "z"}, selon ce
qui sera le plus simple.
Je voudrais, Í  partir de keys (qu'il soit liste, tuple ou set) et de mon
dictionnaire, obtenir un dictionnaire ne contenant que les entrées présentes
dans keys, dans mon exemple "b", "c" et "t", pas l'entrée "m", sans que cela
ne provoque une erreur Í  cause de "z".
Donc :
resultat = { "t" : "TRUC", "b" : "BIDULE", "c" : "CHOSE" }
====>
Et maintenant le vrai problème.
Je voudrais appeler une fonction du type :
def lafonction(b=None, c=None, t=None, z=None):
....
en lui passant les valeurs pour b, c, t et z, si elles existent, se trouvant
dans mon dictionnaire mondict. Du coup un truc du genre :
lafonction(**mondict)
mais sans que cela provoque une erreur Í  cause de l'entrée "m".
Cordialement,
Avatar
rejoc
Désolé, j'arrive un peu tard...
Après, pour la fonction, tu peux extraire les clefs en récupérant la
signature et construire ton "keys" dynamiquement...
Le 28/05/2021 21:45, rejoc a écrit :
Ca fait pas le job ??
new_dict = dict((k, v) for k, v in mondict.items() if k in keys)
Le 25/05/2021 00:13, Olivier Miakinen a écrit :
Bonjour,
Je cherche Í  résoudre élégamment un problème. Comme souvent j'ai déjÍ 
une idée de la solution, d'o͹ ma question consistant Í  extraire un
sous-dictionnaire d'un dictionnaire. Mais dans un second temps je vais
exposer le vrai problème au cas o͹ mon idée ne serait pas optimale.
====>>
Voici donc ma question. Supposons que j'ai un dictionnaire, par exemple
mondict = { "t" : "TRUC", "m" : "MACHIN", "b" : "BIDULE", "c" :
"CHOSE" }.
J'ai par ailleurs une liste de clés, keys = ["b", "c", "t", "z"], ou
un tuple
keys = ("b", "c", "t", "z"), ou un set keys = {"b", "c", "t", "z"},
selon ce
qui sera le plus simple.
Je voudrais, Í  partir de keys (qu'il soit liste, tuple ou set) et de mon
dictionnaire, obtenir un dictionnaire ne contenant que les entrées
présentes
dans keys, dans mon exemple "b", "c" et "t", pas l'entrée "m", sans
que cela
ne provoque une erreur Í  cause de "z".
Donc :
resultat = { "t" : "TRUC", "b" : "BIDULE", "c" : "CHOSE" }
====>>
Et maintenant le vrai problème.
Je voudrais appeler une fonction du type :
def lafonction(b=None, c=None, t=None, z=None):
....
en lui passant les valeurs pour b, c, t et z, si elles existent, se
trouvant
dans mon dictionnaire mondict. Du coup un truc du genre :
lafonction(**mondict)
mais sans que cela provoque une erreur Í  cause de l'entrée "m".
Cordialement,
Avatar
Olivier Miakinen
Bonjour rejoc,
Le 28/05/2021 21:52, rejoc s'est répondu :
Désolé, j'arrive un peu tard...

;-)
Après, pour la fonction, tu peux extraire les clefs en récupérant la
signature et construire ton "keys" dynamiquement...

Je n'en ai pas besoin pour le moment puisque je connais exactement les
paramètres des deux fonctions que j'appelle, mais en effet c'était sympa
d'en parler au cas o͹ j'aurais pu en avoir besoin. Merci pour cela.
Le 28/05/2021 21:45, rejoc a écrit :
[citation intégrale des deux articles précédents]


Ça par contre tu pouvais t'en dispenser. Pour le coup c'est moi qui vais
te donner une info :
<http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html>.
Cordialement,
--
Olivier Miakinen
Avatar
rejoc
Bonjour,
Le 29/05/2021 11:07, Olivier Miakinen a écrit :
<http://www.usenet-fr.net/fur/usenet/repondre-sur-usenet.html>.

J'en prends bonne note ;-)
Quant Í  mon habitude de répondre au dessus du message, ça vient de
l'époque (IP n'existait pas encore, ni ethernet...) o͹ les messages
s'affichaient sur un terminal de 24 lignes et o͹ il fallait appuyer sur
RETURN pour passer aux lignes suivantes. Et si on appuyait sur RETURN
une fois de trop, on passait au message suivant. Alors, revenir en
arrière était une galère !
Aujourd'hui c'est pareil. Si ce qui est important n'apparait pas dans
les 10 premières lignes, je zappe.
Bonne nuit.
Avatar
Nicolas
Même si ce n'est pas nécessaire ici, tu peux voir les choses autrement :
Le temps CPU non utilisé, c'est de l'énergie économisée.

Certes. Du coup je pourrais faire une boucle testant un million de fois
chacune des méthodes afin de savoir au finale laquelle est la plus rapide.
Mais avant de rentabiliser l'énergie perdue par mon test il va me falloir
quelques années d'utilisation du programme dÍ»ment optimisé. ;-)

Mais peut-être qu'un jour ton code se retrouvera dans une librairie
téléchargée des millions de fois et exécutée sur tous les
PC/téléphones/tablettes/systèmes embarqués du monde ;)
Avatar
Olivier Miakinen
Le 31/05/2021 08:48, Nicolas a écrit :
Même si ce n'est pas nécessaire ici, tu peux voir les choses autrement :
Le temps CPU non utilisé, c'est de l'énergie économisée.

Certes. Du coup je pourrais faire une boucle testant un million de fois
chacune des méthodes afin de savoir au finale laquelle est la plus rapide.
Mais avant de rentabiliser l'énergie perdue par mon test il va me falloir
quelques années d'utilisation du programme dÍ»ment optimisé. ;-)

Mais peut-être qu'un jour ton code se retrouvera dans une librairie
téléchargée des millions de fois et exécutée sur tous les
PC/téléphones/tablettes/systèmes embarqués du monde ;)

Il se trouve que non. Tu ne savais pas Í  quoi mon programme est censé servir,
mais c'est typiquement le genre de programme que je me dois de ne pas partager.
<http://www.usenet-fr.net/fur/usenet/abus/cancel-faq-fr-1.html>
<cit. IV. E.>
Donner un robot-annulateur, c'est comme donner une arme chargée, sans
sécurité. Même si celui Í  qui on le donne est bien intentionné, les erreurs
sont fatales. Vous avez besoin d'une formation correcte auparavant. Bien
sͻr, il y a des gens qui vous donneront l'arme sans l'entraͮnement, mais on
peut se poser des questions sur leur motivation...
En général, peu de gens accepteront de vous donner leur code avant que vous
ne sachiez parfaitement vous servir d'un robot-annulateur. Ceux-ci sont
dangereux et peuvent être utilisés Í  mauvais escient. De plus, si vous
commettez une bourde avec un robot-annulateur, vous causerez de graves
problèmes, et on peut commettre assez facilement une bourde avec un
robot-annulateur. Pour toutes ces raisons, on considère généralement que
seuls ceux qui arrivent Í  écrire leur propre robot-annulateur sont capables
d'en posséder un.
</cit.>
--
Olivier Miakinen
1 2 3