Groups | Search | Server Info | Keyboard shortcuts | Login | Register [http] [https] [nntp] [nntps]


Groups > fr.comp.lang.python > #3808 > unrolled thread

Vérifier la présence de plusieurs clés dans un dictionnaire

Started byOlivier Miakinen <om+news@miakinen.net>
First post2022-04-25 23:56 +0200
Last post2022-04-27 15:10 +0200
Articles 9 — 3 participants

Back to article view | Back to fr.comp.lang.python


Contents

  Vérifier la présence de plusieurs clés dans un dictionnaire Olivier Miakinen <om+news@miakinen.net> - 2022-04-25 23:56 +0200
    Re: Vérifier la présence de plusieurs clés dans un dictionnaire Olivier Miakinen <om+news@miakinen.net> - 2022-04-26 00:06 +0200
      Re: Vérifier la présence de plusieurs clés dans un dictionnaire Nicolas <nicolasp@aaton.com> - 2022-04-26 10:03 +0200
      Re: Vérifier la présence de plusieurs clés dans un dictionnaire Alain Ketterlin <alain@universite-de-strasbourg.fr.invalid> - 2022-04-26 11:55 +0200
        Re: Vérifier la présence de plusieurs clés dans un dictionnaire Olivier Miakinen <om+news@miakinen.net> - 2022-04-26 19:01 +0200
          Re: Vérifier la présence de plusieurs clés dans un dictionnaire Alain Ketterlin <alain@universite-de-strasbourg.fr.invalid> - 2022-04-26 19:37 +0200
            Re: Vérifier la présence de plusieurs clés dans un dictionnaire Olivier Miakinen <om+news@miakinen.net> - 2022-04-26 22:07 +0200
        Re: Vérifier la présence de plusieurs clés dans un dictionnaire Olivier Miakinen <om+news@miakinen.net> - 2022-04-26 22:32 +0200
      Re: Vérifier la présence de plusieurs clés dans un dictionnaire Olivier Miakinen <om+news@miakinen.net> - 2022-04-27 15:10 +0200

#3808 — Vérifier la présence de plusieurs clés dans un dictionnaire

FromOlivier Miakinen <om+news@miakinen.net>
Date2022-04-25 23:56 +0200
SubjectVérifier la présence de plusieurs clés dans un dictionnaire
Message-ID<t475fb$17ub$1@cabale.usenet-fr.net>
Bonjour,

Le test « key in d » vérifie la présence d'une clé dans un dictionnaire.

Soit maintenant une liste de plusieurs clés keys=[key1, key2, ... keyn].

Quelle serait la façon la plus économique pour vérifier que toutes les clés
listées dans keys sont présentes dans le dictionnaire d ? Je n'ai pas besoin
de savoir précisément quelles clés sont présentes, je voudrais juste un test
qui me réponde True si tous les élements de keys sont bien des clés dans d,
False si au moins un élément de keys n'est pas une clé dans d.

Cordialement,
-- 
Olivier Miakinen

[toc] | [next] | [standalone]


#3809

FromOlivier Miakinen <om+news@miakinen.net>
Date2022-04-26 00:06 +0200
Message-ID<t4761d$1839$1@cabale.usenet-fr.net>
In reply to#3808
Je réponds à moi-même, je crois que j'ai trouvé...

Le 25/04/2022 23:56, Olivier Miakinen a écrit :
> 
> Le test « key in d » vérifie la présence d'une clé dans un dictionnaire.
> 
> Soit maintenant une liste de plusieurs clés keys=[key1, key2, ... keyn].
> 
> Quelle serait la façon la plus économique pour vérifier que toutes les clés
> listées dans keys sont présentes dans le dictionnaire d ? Je n'ai pas besoin
> de savoir précisément quelles clés sont présentes, je voudrais juste un test
> qui me réponde True si tous les élements de keys sont bien des clés dans d,
> False si au moins un élément de keys n'est pas une clé dans d.

Ceci devrait faire l'affaire :
  not (keys - d.keys())

Sauf erreur de ma part, ça répondra True si la différence entre mon tableau
de clés et les vraies clés du dictionnaire est un ensemble vide, False si
la différence contient au moins une clé (présente donc dans keys et pas dans
d.keys())

-- 
Olivier Miakinen

[toc] | [prev] | [next] | [standalone]


#3811

FromNicolas <nicolasp@aaton.com>
Date2022-04-26 10:03 +0200
Message-ID<6267a754$0$18039$426a34cc@news.free.fr>
In reply to#3809
Le 26/04/2022 à 00:06, Olivier Miakinen a écrit :
> Je réponds à moi-même, je crois que j'ai trouvé...
> 
> Le 25/04/2022 23:56, Olivier Miakinen a écrit :
>>
>> Le test « key in d » vérifie la présence d'une clé dans un dictionnaire.
>>
>> Soit maintenant une liste de plusieurs clés keys=[key1, key2, ... keyn].
>>
>> Quelle serait la façon la plus économique pour vérifier que toutes les clés
>> listées dans keys sont présentes dans le dictionnaire d ? Je n'ai pas besoin
>> de savoir précisément quelles clés sont présentes, je voudrais juste un test
>> qui me réponde True si tous les élements de keys sont bien des clés dans d,
>> False si au moins un élément de keys n'est pas une clé dans d.
> 
> Ceci devrait faire l'affaire :
>    not (keys - d.keys())
> 
> Sauf erreur de ma part, ça répondra True si la différence entre mon tableau
> de clés et les vraies clés du dictionnaire est un ensemble vide, False si
> la différence contient au moins une clé (présente donc dans keys et pas dans
> d.keys())
> 

Jolie solution. Je n'y aurait pas pensé.
+1

[toc] | [prev] | [next] | [standalone]


#3814

FromAlain Ketterlin <alain@universite-de-strasbourg.fr.invalid>
Date2022-04-26 11:55 +0200
Message-ID<878rrsw4mx.fsf@universite-de-strasbourg.fr.invalid>
In reply to#3809
Olivier Miakinen <om+news@miakinen.net> writes:

>> Soit maintenant une liste de plusieurs clés keys=[key1, key2, ... keyn].
>> 
>> Quelle serait la façon la plus économique pour vérifier que toutes les clés
>> listées dans keys sont présentes dans le dictionnaire d ? Je n'ai pas besoin
>> de savoir précisément quelles clés sont présentes, je voudrais juste un test
>> qui me réponde True si tous les élements de keys sont bien des clés dans d,
>> False si au moins un élément de keys n'est pas une clé dans d.
>
> Ceci devrait faire l'affaire :
>   not (keys - d.keys())
>
> Sauf erreur de ma part, ça répondra True si la différence entre mon tableau
> de clés et les vraies clés du dictionnaire est un ensemble vide, False si
> la différence contient au moins une clé (présente donc dans keys et pas dans
> d.keys())

Je m'interroge sur cette façon de faire... keys est une liste, d.keys()
une "vue", je ne vois pas bien de quel opérateur - il s'agit (le
résultat est un set, en tout cas). Bref, cela fait bien ce que tu veux
apparemment.

Si le dictionnaire est volumineux et la liste courte, il vaut peut-être
mieux faire quelque chose comme

all (k in d for k in keys)

cela évitera la création explicite d'un set dans le seul but de tester
s'il est vide, et j'imagine que cela arrête la recherche au premier
False, ce que semble confirmer la doc de all.

(Difficile d'en dire plus parce que toutes ces opérations ont une
complexité --voire un comportement -- mal documentée.)

-- Alain.

[toc] | [prev] | [next] | [standalone]


#3819

FromOlivier Miakinen <om+news@miakinen.net>
Date2022-04-26 19:01 +0200
Message-ID<t498hb$21nm$1@cabale.usenet-fr.net>
In reply to#3814
Le 26/04/2022 à 11:55, Alain Ketterlin a écrit :
>>
>>   not (keys - d.keys())
> 
> Je m'interroge sur cette façon de faire... keys est une liste, d.keys()
> une "vue", je ne vois pas bien de quel opérateur - il s'agit (le
> résultat est un set, en tout cas). Bref, cela fait bien ce que tu veux
> apparemment.

Tu as raison de t'interroger, parce que j'ai lu trop vite la doc :

<https://docs.python.org/fr/3.8/library/stdtypes.html#frozenset.difference>
§
Remarque : Les méthodes union(), intersection(), difference(), et
symmetric_difference(), issubset(), et issuperset() acceptent n'importe
quel itérable comme argument, contrairement aux opérateurs équivalents
qui n'acceptent que des sets.
§

En lisant cette remarque, j'ai cru à tort qu'elle disait que « - »
acceptait n'importe quel itérable à gauche et à droite, alors qu'au
ça ne vaut pour « difference() », et encore, seulement pour son
argument !

Bon, il se trouve que ça marche (et que ça retourne effectivement un
set) mais je suis bien sûr preneur d'une meilleure solution.

> Si le dictionnaire est volumineux et la liste courte, il vaut peut-être
> mieux faire quelque chose comme
> 
> all (k in d for k in keys)
> 
> cela évitera la création explicite d'un set dans le seul but de tester
> s'il est vide, et j'imagine que cela arrête la recherche au premier
> False, ce que semble confirmer la doc de all.

Ni le dictionnaire ni la liste ne sont très gros (moins de 20 entrées
pour le dictionnaire, et entre 3 et 6 pour la liste), mais ta solution
présente surtout l'intérêt d'être plus lisible. Cette commande 'all'
est vraiment ce qu'il me faut !

Bon, ayant créé un set, j'en avais profité pour l'afficher dans les
traces (« les données manquantes sont... »), mais je n'en ai pas plus
besoin que ça. Merci de m'avoir répondu, je pense que je vais vraiment
retenir ta proposition. J'essaye ça dès que possible.

> (Difficile d'en dire plus parce que toutes ces opérations ont une
> complexité --voire un comportement -- mal documentée.)

Certes. D'où la nécessité de n'utiliser que ce qui est documenté, parce
que le reste risquerait de changer de comportement d'une version à une
autre.

-- 
Olivier Miakinen

[toc] | [prev] | [next] | [standalone]


#3820

FromAlain Ketterlin <alain@universite-de-strasbourg.fr.invalid>
Date2022-04-26 19:37 +0200
Message-ID<874k2fwxsi.fsf@universite-de-strasbourg.fr.invalid>
In reply to#3819
Olivier Miakinen <om+news@miakinen.net> writes:

>>>   not (keys - d.keys())

> <https://docs.python.org/fr/3.8/library/stdtypes.html#frozenset.difference>
> §
> Remarque : Les méthodes union(), intersection(), difference(), et
> symmetric_difference(), issubset(), et issuperset() acceptent n'importe
> quel itérable comme argument, contrairement aux opérateurs équivalents
> qui n'acceptent que des sets.
> §
>
> En lisant cette remarque, j'ai cru à tort qu'elle disait que « - »
> acceptait n'importe quel itérable à gauche et à droite, alors qu'au
> ça ne vaut pour « difference() », et encore, seulement pour son
> argument !
>
> Bon, il se trouve que ça marche (et que ça retourne effectivement un
> set) mais je suis bien sûr preneur d'une meilleure solution.

Oui, mais je pense que ça marche grâce aux "reflected/swapped operands",
qui fait si il n'y a pas de __sub__ sur list, la méthode __rsub__ de set
(ou ce que renvoie keys()) est utilisée...

https://docs.python.org/3/reference/datamodel.html#object.__radd__

>> all (k in d for k in keys)

> Ni le dictionnaire ni la liste ne sont très gros (moins de 20 entrées
> pour le dictionnaire, et entre 3 et 6 pour la liste), mais ta solution
> présente surtout l'intérêt d'être plus lisible. Cette commande 'all'
> est vraiment ce qu'il me faut !

Dans ce cas, "beauty is in the eye of the beholder", choisis ce que tu
comprendras le plus facilement quand tu reliras le code dans 3
semaines/mois/années/.

-- Alain.

[toc] | [prev] | [next] | [standalone]


#3821

FromOlivier Miakinen <om+news@miakinen.net>
Date2022-04-26 22:07 +0200
Message-ID<t49jeo$24dl$1@cabale.usenet-fr.net>
In reply to#3820
Le 26/04/2022 19:37, Alain Ketterlin a écrit :
> 
> Oui, mais je pense que ça marche grâce aux "reflected/swapped operands",
> qui fait si il n'y a pas de __sub__ sur list, la méthode __rsub__ de set
> (ou ce que renvoie keys()) est utilisée...
> 
> https://docs.python.org/3/reference/datamodel.html#object.__radd__

Eh bien je suis vraiment content d'avoir posé la question, parce que
j'étais loin d'imaginer tous ces mécanismes et que je trouve ça
passionnant !

Par ailleurs tu as raison, le __sub__ n'existe pas pour une liste alors que
le __rsub__ fonctionne sur un dict_keys :

% keys.__sub__(d.keys())
Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
AttributeError: 'list' object has no attribute '__sub__'

% d.keys().__rsub__(keys)
set()

% d.keys()
dict_keys([ ... ])

>>> all (k in d for k in keys)
> 
>> [...] ta solution
>> présente surtout l'intérêt d'être plus lisible. [...]
> 
> Dans ce cas, "beauty is in the eye of the beholder", choisis ce que tu
> comprendras le plus facilement quand tu reliras le code dans 3
> semaines/mois/années/.

Oui, mais il faut aussi penser que ce soit quelqu'un d'autre que moi
qui puisse devoir relire le code plus tard, alors j'ajouterai aussi un
commentaire disant en substance « on vérifie que toutes les clés requises
sont dans le dictionnaire ».

-- 
Olivier Miakinen

[toc] | [prev] | [next] | [standalone]


#3822

FromOlivier Miakinen <om+news@miakinen.net>
Date2022-04-26 22:32 +0200
Message-ID<t49kst$24op$1@cabale.usenet-fr.net>
In reply to#3814
Le 26/04/2022 11:55, Alain Ketterlin a écrit :
> 
> all (k in d for k in keys)

En cherchant la doc pour all() j'ai également trouvé any() qui va
m'être tout aussi utile :
<https://docs.python.org/fr/3/library/functions.html?highlight=any#all>

Encore merci !

-- 
Olivier Miakinen

[toc] | [prev] | [next] | [standalone]


#3823

FromOlivier Miakinen <om+news@miakinen.net>
Date2022-04-27 15:10 +0200
Message-ID<t4bfbf$6s0$1@cabale.usenet-fr.net>
In reply to#3809
Le 26/04/2022 00:06, je me répondais :
>> 
>> Soit maintenant une liste de plusieurs clés keys=[key1, key2, ... keyn].

En réalité je ne sais pas pourquoi j'en ai fait une liste, c'est réellement
un ensemble qui correspond le mieux au besoin : keys={key1, key2, ... keyn}

>> Quelle serait la façon la plus économique pour vérifier que toutes les clés
>> listées dans keys sont présentes dans le dictionnaire d ? Je n'ai pas besoin
>> de savoir précisément quelles clés sont présentes, je voudrais juste un test
>> qui me réponde True si tous les élements de keys sont bien des clés dans d,
>> False si au moins un élément de keys n'est pas une clé dans d.
> 
> Ceci devrait faire l'affaire :
>   not (keys - d.keys())

Alain Ketterlin m'a donné une solution élégante avec all() mais je viens
d'en trouver une autre, à condition d'avoir un ensemble de clés plutôt
qu'une liste, et sans créer de nouveau set :
 keys.issubset(d.keys())

D'ailleurs j'utilisais déjà une construction similaire ailleurs dans le
code, quand je voulais vérifier au contraire que toutes les clés du
dictionnaire font partie de celles autorisées dans l'ensemble keys :
 keys.issuperset(d.keys())

<https://docs.python.org/fr/3/library/stdtypes.html?highlight=issuperset#frozenset.issubset>

Quant à ce que j'avais résolu avec un any(), il pourrait aussi se faire
avec un « not isdisjoint() ».

-- 
Olivier Miakinen

[toc] | [prev] | [standalone]


Back to top | Article view | fr.comp.lang.python


csiph-web