Comment supprimer une clé d'un dictionnaire Python?


Réponses:


2843

Pour supprimer une clé, qu'elle se trouve dans le dictionnaire ou non, utilisez la forme à deux arguments de dict.pop():

my_dict.pop('key', None)

Cela retournera my_dict[key]s'il keyexiste dans le dictionnaire, et Nonesinon. Si le deuxième paramètre n'est pas spécifié (c'est-à-dire. my_dict.pop('key')) Et keyn'existe pas, a KeyErrorest levé.

Pour supprimer une clé dont l'existence est garantie, vous pouvez également utiliser

del my_dict['key']

Cela soulèvera un KeyErrorsi la clé n'est pas dans le dictionnaire.


153
Parfois, un avantage d'utiliser pop()over del: il renvoie la valeur de cette clé. De cette façon, vous pouvez obtenir et supprimer une entrée d'un dict dans une seule ligne de code.
kratenko

7
Dans la question, il n'est pas nécessaire de conserver la valeur. Cela ne ferait qu'ajouter une complexité inutile. La réponse de @zigg (ci-dessous) est bien meilleure.
Salvatore Cosentino

10
@SalvatoreCosentino Je ne peux pas suivre votre argument. En quoi le code de cette réponse est-il plus complexe que le code de l'autre réponse?
Sven Marnach

33
@SalvatoreCosentino Non, ignorer la valeur de retour d'une fonction n'est pas du tout inefficace. Bien au contraire - cette solution est beaucoup plus rapide que la solution try/ exceptsi la clé n'existe pas. Vous pourriez trouver l'un ou l'autre plus facile à lire, ce qui est bien. Les deux sont en Python idiomatique, alors choisissez ce que vous préférez. Mais prétendre que cette réponse est plus complexe ou inefficace n'a tout simplement aucun sens.
Sven Marnach

5
@ user5359531 Je ne comprends pas. Et en quoi est-ce un problème? Aucune des méthodes sur les types intégrés de Python ne retourne self, il serait donc plutôt surprenant que celle-ci le fasse.
Sven Marnach

353

Spécifiquement pour répondre "y a-t-il une façon de faire cela sur une ligne?"

if 'key' in my_dict: del my_dict['key']

... eh bien, vous avez demandé ;-)

Vous devez considérer, cependant, que cette façon de supprimer un objet de a dictn'est pas atomique - il est possible qu'elle 'key'se trouve my_dictpendant l' ifinstruction, mais peut être supprimée avant l' delexécution, auquel cas delelle échouera avec a KeyError. Compte tenu de cela, il serait plus sûr d' utiliserdict.pop soit quelque chose du genre

try:
    del my_dict['key']
except KeyError:
    pass

qui, bien sûr, n'est certainement pas un vol simple.


27
Oui, popc'est définitivement plus concis, bien qu'il y ait un avantage clé à le faire de cette façon: c'est immédiatement clair ce qu'il fait.
zigg

4
La try/exceptdéclaration est plus chère. La levée d'une exception est lente.
Chris Barker

16
@ChrisBarker J'ai trouvé si la clé existe, tryest légèrement plus rapide, mais si ce n'est pas le cas, elle tryest en effet beaucoup plus lente. popest assez cohérent mais plus lent que tous mais tryavec une clé non présente. Voir gist.github.com/zigg/6280653 . En fin de compte, cela dépend de la fréquence à laquelle vous vous attendez à ce que la clé soit réellement dans le dictionnaire, et si vous avez besoin ou non d'atomicité - et, bien sûr, si vous vous lancez dans une optimisation prématurée;)
zigg

9
Je pense que la valeur de la clarté ne doit pas être négligée. +1 pour cela.
Juan Carlos Coto

2
en ce qui concerne les frais d'essai / sauf, vous pouvez également y aller if 'key' in mydict: #then del.... J'avais besoin de retirer une clé / val d'un dict pour analyser correctement, pop n'était pas une solution parfaite.
Marc

153

Il m'a fallu un certain temps pour comprendre ce qui se passe exactement my_dict.pop("key", None). Je vais donc ajouter ceci comme réponse pour gagner du temps sur Google:

pop(key[, default])

Si la clé est dans le dictionnaire, supprimez-la et retournez sa valeur, sinon retournez par défaut . Si la valeur par défaut n'est pas indiquée et que la clé n'est pas dans le dictionnaire, un KeyErrorest levé.

Documentation


15
Tapez simplement help (dict.pop) dans l'interpréteur python.
David Mulder

13
help () et dir () peuvent être vos amis lorsque vous avez besoin de savoir ce que fait quelque chose.
David Mulder

3
ou dict.pop?en IPython.
Erik Kaplun

51

del my_dict[key]est légèrement plus rapide que my_dict.pop(key)pour supprimer une clé d'un dictionnaire lorsque la clé existe

>>> import timeit
>>> setup = "d = {i: i for i in range(100000)}"

>>> timeit.timeit("del d[3]", setup=setup, number=1)
1.79e-06
>>> timeit.timeit("d.pop(3)", setup=setup, number=1)
2.09e-06
>>> timeit.timeit("d2 = {key: val for key, val in d.items() if key != 3}", setup=setup, number=1)
0.00786

Mais lorsque la clé n'existe pas, if key in my_dict: del my_dict[key]c'est légèrement plus rapide que my_dict.pop(key, None). Les deux sont au moins trois fois plus rapides que deldans une instruction try/ except:

>>> timeit.timeit("if 'missing key' in d: del d['missing key']", setup=setup)
0.0229
>>> timeit.timeit("d.pop('missing key', None)", setup=setup)
0.0426
>>> try_except = """
... try:
...     del d['missing key']
... except KeyError:
...     pass
... """
>>> timeit.timeit(try_except, setup=setup)
0.133

1
Mesurer le timing d'une opération aussi rapide est assez stupide. Votre code n'ira probablement pas beaucoup plus vite car vous avez changé de a popen a del. La création du dictionnaire supprimera complètement les éléments qu'il contient.
Boris

1
@Boris - ceci est utile comme exercice général.
marguerite

1
@daisy ce que je dis, c'est que vous devez choisir la syntaxe la plus lisible et non l'opération qui est 300 nanosecondes plus rapide (c'est littéralement la différence entre delet à poppartir du premier ensemble de temporisations ci-dessus)
Boris

De plus, ces opérations sont si rapides que ces temporisations ne sont pas fiables.
Boris

46

Si vous devez supprimer un grand nombre de clés d'un dictionnaire sur une seule ligne de code, je pense que l'utilisation de map () est assez succincte et lisible en Pythonic:

myDict = {'a':1,'b':2,'c':3,'d':4}
map(myDict.pop, ['a','c']) # The list of keys to remove
>>> myDict
{'b': 2, 'd': 4}

Et si vous avez besoin de détecter des erreurs lorsque vous entrez une valeur qui n'est pas dans le dictionnaire, utilisez lambda à l'intérieur de map () comme ceci:

map(lambda x: myDict.pop(x,None), ['a', 'c', 'e'])
[1, 3, None] # pop returns
>>> myDict
{'b': 2, 'd': 4}

ou dans python3, vous devez utiliser une liste de compréhension à la place:

[myDict.pop(x, None) for x in ['a', 'c', 'e']]

Ça marche. Et «e» n'a pas causé d'erreur, même si myDict n'avait pas de clé «e».


42
Cela ne fonctionnera pas dans Python 3 car mapet les amis sont maintenant paresseux et renvoient des itérateurs. L'utilisation mapd'effets secondaires est généralement considérée comme une mauvaise pratique; une for ... inboucle standard serait mieux. Voir Vues et itérateurs au lieu de listes pour plus d'informations.
Greg Krimer

5
Indépendamment du goût et du style de pratique, les compréhensions de liste devraient toujours fonctionner dans Py3 [myDict.pop(i, None) for i in ['a', 'c']], car elles offrent une alternative générale à map(et filter).
Michael Ekoka

@MichaelEkoka, vous ne devez pas utiliser de listes de compréhension pour leurs effets secondaires, utilisez une for ... inboucle régulière .
Boris

@Boris Vous avez probablement raison. Ma réponse concerne spécifiquement l'utilisation map(), qui est souvent utilisée pour ses effets secondaires. L'alternative recommandée en Python est la compréhension de la liste, qui à mon avis est encore assez lisible et cognitivement légère comme une ligne (voir la question). Utilisées uniquement pour leurs effets secondaires, les deux constructions aboutissent en effet à une liste inutile, qui peut être inefficace. En ce qui concerne Python3, je ne connais pas de fonction intégrée qui puisse itérer en toute sécurité et élégance à travers une expression de générateur, sans sous-produit coûteux, par exemple loop(d.pop(k) for k in ['a', 'b']).
Michael Ekoka

Je suis amusé de constater que ma réponse la plus votée de tous les temps comprend des hacks que je n'utiliserais jamais. La compréhension de la liste (option 3) est à mon avis l'approche la moins mauvaise. Utilisez celui-là.
Marc Maxmeister

20

Vous pouvez utiliser une compréhension de dictionnaire pour créer un nouveau dictionnaire avec cette clé supprimée:

>>> my_dict = {k: v for k, v in my_dict.items() if k != 'key'}

Vous pouvez supprimer par conditions. Aucune erreur s'il keyn'existe pas.



7

Nous pouvons supprimer une clé d'un dictionnaire Python par les approches suivantes.

En utilisant le delmot - clé; c'est presque la même approche que vous l'avez fait -

 myDict = {'one': 100, 'two': 200, 'three': 300 }
 print(myDict)  # {'one': 100, 'two': 200, 'three': 300}
 if myDict.get('one') : del myDict['one']
 print(myDict)  # {'two': 200, 'three': 300}

Ou

Nous pouvons faire comme suit:

Mais il faut garder à l'esprit que, dans ce processus, il ne supprimera aucune clé du dictionnaire plutôt que d' exclure une clé spécifique de ce dictionnaire. De plus, j'ai observé qu'il renvoyait un dictionnaire qui n'était pas commandé de la même manière que myDict.

myDict = {'one': 100, 'two': 200, 'three': 300, 'four': 400, 'five': 500}
{key:value for key, value in myDict.items() if key != 'one'}

Si nous l'exécutons dans le shell, il exécutera quelque chose comme {'five': 500, 'four': 400, 'three': 300, 'two': 200}- notez que ce n'est pas le même ordre que myDict. Encore une fois, si nous essayons d'imprimer myDict, nous pouvons voir toutes les clés, y compris celles que nous avons exclues du dictionnaire par cette approche. Cependant, nous pouvons créer un nouveau dictionnaire en affectant l'instruction suivante à une variable:

var = {key:value for key, value in myDict.items() if key != 'one'}

Maintenant, si nous essayons de l'imprimer, il suivra l'ordre des parents:

print(var) # {'two': 200, 'three': 300, 'four': 400, 'five': 500}

Ou

Utilisation de la pop()méthode.

myDict = {'one': 100, 'two': 200, 'three': 300}
print(myDict)

if myDict.get('one') : myDict.pop('one')
print(myDict)  # {'two': 200, 'three': 300}

La différence entre delet popest que, en utilisant la pop()méthode, nous pouvons réellement stocker la valeur de la clé si nécessaire, comme suit:

myDict = {'one': 100, 'two': 200, 'three': 300}
if myDict.get('one') : var = myDict.pop('one')
print(myDict) # {'two': 200, 'three': 300}
print(var)    # 100

Fourchez cet élément pour référence future, si vous trouvez cela utile.


1
Ne pas utiliser if myDict.get('one')pour vérifier si une clé est présente! Il échoue si myDict ['one'] a une valeur de falsey. De plus, les dict n'ont pas d'ordre inhérent, il n'est donc pas logique de le mentionner.
Rob

Les textes @Rob sont classés par ordre d'insertion à partir de CPython 3.6 et de toutes les autres implémentations Python à partir de 3.7.
Boris

4

Vous pouvez utiliser la gestion des exceptions si vous voulez être très bavard:

try: 
    del dict[key]

except KeyError: pass

Cependant, c'est plus lent que la pop()méthode, si la clé n'existe pas.

my_dict.pop('key', None)

Cela n'aura pas d'importance pour quelques clés, mais si vous faites cela à plusieurs reprises, alors la dernière méthode est une meilleure mise.

L'approche la plus rapide est la suivante:

if 'key' in dict: 
    del myDict['key']

Mais cette méthode est dangereuse car si elle 'key'est supprimée entre les deux lignes, un KeyErrorsera levé.


1

Je préfère la version immuable

foo = {
    1:1,
    2:2,
    3:3
}
removeKeys = [1,2]
def woKeys(dct, keyIter):
    return {
        k:v
        for k,v in dct.items() if k not in keyIter
    }

>>> print(woKeys(foo, removeKeys))
{3: 3}
>>> print(foo)
{1: 1, 2: 2, 3: 3}

1

Une autre méthode consiste à utiliser items () + compréhension du dict

items () couplé à la compréhension de dict peut également nous aider à réaliser la tâche de suppression de paire clé-valeur, mais il présente l'inconvénient de ne pas être une technique de dict en place. En fait, un nouveau dict si créé à l'exception de la clé que nous ne souhaitons pas inclure.

test_dict = {"sai" : 22, "kiran" : 21, "vinod" : 21, "sangam" : 21} 

# Printing dictionary before removal 
print ("dictionary before performing remove is : " + str(test_dict)) 

# Using items() + dict comprehension to remove a dict. pair 
# removes  vinod
new_dict = {key:val for key, val in test_dict.items() if key != 'vinod'} 

# Printing dictionary after removal 
print ("dictionary after remove is : " + str(new_dict)) 

Production:

dictionary before performing remove is : {'sai': 22, 'kiran': 21, 'vinod': 21, 'sangam': 21}
dictionary after remove is : {'sai': 22, 'kiran': 21, 'sangam': 21}

0

Filtre unique sur clé

  • retourner "clé" et la supprimer de my_dict si "clé" existe dans my_dict
  • retourne Aucun si "clé" n'existe pas dans mon_dict

cela va changer my_dicten place (mutable)

my_dict.pop('key', None)

Plusieurs filtres sur les touches

générer un nouveau dict (immuable)

dic1 = {
    "x":1,
    "y": 2,
    "z": 3
}

def func1(item):
    return  item[0]!= "x" and item[0] != "y"

print(
    dict(
        filter(
            lambda item: item[0] != "x" and item[0] != "y", 
            dic1.items()
            )
    )
)
En utilisant notre site, vous reconnaissez avoir lu et compris notre politique liée aux cookies et notre politique de confidentialité.
Licensed under cc by-sa 3.0 with attribution required.