160 votes

Suppression de plusieurs clés d'un dictionnaire en toute sécurité

Je sais comment supprimer une entrée, 'key' de mon dictionnaire d en toute sécurité. Tu le fais :

if d.has_key('key'):
    del d['key']

Cependant, je dois supprimer plusieurs entrées d'un dictionnaire en toute sécurité. Je pensais définir les entrées dans un tuple, car j'aurai besoin de le faire plus d'une fois.

entities_to_remove = ('a', 'b', 'c')
for x in entities_to_remove:
    if x in d:
        del d[x]

Cependant, je me demandais s'il n'y avait pas une façon plus intelligente de faire cela ?

3 votes

Le temps de récupération d'un dictionnaire est presque O(1) à cause du hachage. À moins que vous ne supprimiez une proportion importante des entrées, je ne pense pas que vous fassiez beaucoup mieux.

1 votes

La réponse de @mattbornski semble plus canonique, et aussi plus succincte.

2 votes

StackOverflow a parlé : key in d est plus pythique que d.has_key(key) stackoverflow.com/questions/1323410/has-key-or-in

289voto

mattbornski Points 2226

Utilisation de dict.pop :

d = {'some': 'data'}
entries_to_remove = ('any', 'iterable')
for k in entries_to_remove:
    d.pop(k, None)

48 votes

Ceci. C'est le choix de la pythonisse intelligente. dict.pop() élimine la nécessité de tester l'existence des clés. Excellent.

7 votes

Pour ce que ça vaut, je pense .pop() est mauvaise et impythique, et préférerait la réponse acceptée à celle-ci.

7 votes

Un nombre impressionnant de personnes semblent ne pas s'en soucier :) Personnellement, la ligne supplémentaire pour la vérification de l'existence ne me dérange pas, et c'est nettement plus lisible, sauf si vous connaissez déjà pop(). D'un autre côté, si vous essayez de faire cela dans une compréhension ou un lambda en ligne, cette astuce pourrait être d'une grande aide. Je dirais également qu'il est important, à mon avis, de rencontrer les gens là où ils sont. Je ne suis pas sûr que le fait d'être "mauvais et impythique" va donner aux personnes qui lisent ces réponses les conseils pratiques qu'elles recherchent.

99voto

shadyabhi Points 5924

Utilisation de Compréhensions Dict

final_dict = {key: t[key] for key in t if key not in [key1, key2]}

Clé1 y clé2 sont à retirer.

Dans l'exemple ci-dessous, les clés "b" et "c" doivent être supprimées et sont conservées dans une liste de clés.

>>> a
{'a': 1, 'c': 3, 'b': 2, 'd': 4}
>>> keys = ["b", "c"]
>>> print {key: a[key] for key in a if key not in keys}
{'a': 1, 'd': 4}
>>>

4 votes

Nouveau dictionnaire ? liste de compréhension ? Vous devriez adapter la réponse à la personne qui pose la question ;)

0 votes

Ça crée un nouveau dictionnaire, mais c'était une réplique, alors je l'ai mentionnée.

7 votes

Cette solution a un sérieux impact sur les performances lorsque la variable contenant le a une autre utilisation dans le programme. En d'autres termes, un dict dont les clés ont été supprimées est beaucoup plus efficace qu'un dict nouvellement créé avec les éléments conservés.

76voto

Glaslos Points 829

Pourquoi pas comme ça :

entries = ('a', 'b', 'c')
the_dict = {'b': 'foo'}

def entries_to_remove(entries, the_dict):
    for key in entries:
        if key in the_dict:
            del the_dict[key]

Une version plus compacte a été fournie par mattbornski en utilisant dict.pop()

17 votes

Ajouter ceci pour les personnes venant d'un moteur de recherche. Si les clés sont connues (lorsque la sécurité n'est pas un problème), plusieurs clés peuvent être supprimées en une seule ligne comme ceci del dict['key1'], dict['key2'], dict['key3']

1 votes

Selon le nombre de clés que vous supprimez, il peut être plus efficace d'utiliser l'option for key in set(the_dict) & entries: et contourner le key in dict test.

24voto

Une solution consiste à utiliser map y filter fonctions

python 2

d={"a":1,"b":2,"c":3}
l=("a","b","d")
map(d.__delitem__, filter(d.__contains__,l))
print(d)

python 3

d={"a":1,"b":2,"c":3}
l=("a","b","d")
list(map(d.__delitem__, filter(d.__contains__,l)))
print(d)

vous obtenez :

{'c': 3}

0 votes

Cela ne fonctionne pas pour moi avec python 3.4 : >>> d={"a":1,"b":2,"c":3} >>> l=("a","b","d") >>> map(d.__delitem__, filter(d.__contains__,l)) <map object at 0x10579b9e8> >>> print(d) {'a': 1, 'b': 2, 'c': 3}

0 votes

@Risadinha list(map(d.__delitem__,filter(d.__contains__,l))) .... dans python 3.4 la fonction map renvoie un itérateur

4 votes

Ou deque(map(...), maxlen=0) afin d'éviter de construire une liste de valeurs None ; d'abord l'importation avec from collections import deque

20voto

Andrew Clark Points 77748

Si vous devez également récupérer les valeurs des clés que vous supprimez, c'est un bon moyen de le faire :

values_removed = [d.pop(k, None) for k in entities_to_remove]

Vous pouvez bien sûr continuer à le faire uniquement pour retirer les clés de l'ordinateur. d mais vous créeriez inutilement la liste des valeurs avec la compréhension de la liste. Il n'est pas non plus très clair d'utiliser une compréhension de liste uniquement pour l'effet secondaire de la fonction.

3 votes

Ou si vous vouliez garder les entrées supprimées comme un dictionnaire : valuesRemoved = dict((k, d.pop(k, None)) for k in entitiesToRemove) et ainsi de suite.

0 votes

Vous pouvez laisser de côté l'affectation à une variable. De cette façon, c'est la solution la plus courte et la plus pythique, et elle devrait être marquée comme la réponse correcte, à mon avis.

Prograide.com

Prograide est une communauté de développeurs qui cherche à élargir la connaissance de la programmation au-delà de l'anglais.
Pour cela nous avons les plus grands doutes résolus en français et vous pouvez aussi poser vos propres questions ou résoudre celles des autres.

Powered by:

X