Supprimer un élément d'un dictionnaire

y a-t-il un moyen de supprimer un élément d'un dictionnaire en Python?

en outre, Comment puis-je supprimer un élément d'un dictionnaire pour retourner une copie (c.-à-d., ne pas modifier l'original)?

891
demandé sur coldspeed 2011-05-01 01:20:57

14 réponses

Le del déclaration supprime un élément:

del d[key]

cependant, ceci mute le dictionnaire existant de sorte que le contenu du dictionnaire change pour quiconque a une référence à la même instance. Pour retourner un nouveau dictionnaire, faire une copie du dictionnaire:

def removekey(d, key):
    r = dict(d)
    del r[key]
    return r

le constructeur dict() fait une copie superficielle . Pour faire un copie en profondeur, voir le copy module .


notez que faire une copie pour chaque dict del /assignment/etc. signifie que vous allez de temps constant à temps linéaire, et aussi en utilisant l'espace linéaire. Pour les petites dicts, ce n'est pas un problème. Mais si vous prévoyez de faire beaucoup de copies de grands dicts, vous voulez probablement une structure de données différente, comme un HAMT (comme décrit dans cette réponse ).

1248
répondu Greg Hewgill 2018-05-15 01:27:47

pop mute le dictionnaire.

 >>>lol = {"hello":"gdbye"}
 >>>lol.pop("hello")
    'gdbye'
 >>> lol
     {}

Si vous voulez garder l'original, vous pouvez simplement copier.

145
répondu Crystal 2017-02-14 11:08:00

je pense que votre solution est la meilleure façon de le faire. Mais si vous voulez une autre solution, vous pouvez créer un nouveau dictionnaire avec l'utilisation des clés de l'ancien dictionnaire sans inclure votre clé spécifiée, comme ceci:

>>> a
{0: 'zero', 1: 'one', 2: 'two', 3: 'three'}
>>> {i:a[i] for i in a if i!=0}
{1: 'one', 2: 'two', 3: 'three'}
56
répondu utdemir 2011-04-30 21:26:40

Le del déclaration est ce que vous cherchez. Si vous avez un dictionnaire nommé foo avec une clé appelée "bar", vous pouvez supprimer "barre" de foo comme ceci:

del foo['bar']

noter que ceci modifie de façon permanente le dictionnaire utilisé. Si vous voulez conserver le dictionnaire original, vous devrez en créer une copie à l'avance:

>>> foo = {'bar': 'baz'}
>>> fu = dict(foo)
>>> del foo['bar']
>>> print foo
{}
>>> print fu
{'bar': 'baz'}

l'appel dict fait une copie superficielle. Si vous voulez une copie profonde, utilisez copy.deepcopy .

Voici une méthode que vous pouvez copier-coller, pour votre commodité:

def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy
47
répondu arussell84 2017-05-30 14:27:40

il y a beaucoup de bonnes réponses, mais je tiens à souligner une chose.

vous pouvez utiliser à la fois dict.pop() méthode et un plus générique del déclaration pour supprimer des éléments d'un dictionnaire. Ils mutent tous les deux le dictionnaire original, donc vous devez faire une copie (voir les détails ci-dessous).

et les deux soulèveront un KeyError si le la clé que vous leur fournissez n'est pas présente dans le dictionnaire:

key_to_remove = "c"
d = {"a": 1, "b": 2}
del d[key_to_remove]  # Raises `KeyError: 'c'`

et

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove)  # Raises `KeyError: 'c'`

Vous devez prendre soin de cela:

en capturant l'exception:

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    del d[key_to_remove]
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

et

key_to_remove = "c"
d = {"a": 1, "b": 2}
try:
    d.pop(key_to_remove)
except KeyError as ex:
    print("No such key: '%s'" % ex.message)

en effectuant un contrôle:

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    del d[key_to_remove]

et

key_to_remove = "c"
d = {"a": 1, "b": 2}
if key_to_remove in d:
    d.pop(key_to_remove)

mais avec pop() il y a aussi un moyen beaucoup plus concis - fournir la valeur de retour par défaut:

key_to_remove = "c"
d = {"a": 1, "b": 2}
d.pop(key_to_remove, None)  # No `KeyError` here

sauf si vous utilisez pop() pour obtenir la valeur d'une clé étant enlevé, vous pouvez fournir n'importe quoi, pas nécessaire None . Bien qu'il puisse être que l'utilisation de del avec in contrôle est légèrement plus rapide en raison de pop() étant une fonction avec son propre complications causant des frais généraux. Généralement ce n'est pas le cas, donc pop() avec la valeur par défaut est suffisant.


quant à la question principale, vous devrez faire une copie de votre dictionnaire, pour sauvegarder le dictionnaire original et en avoir un nouveau sans que la clé soit enlevée.

D'autres personnes ici suggèrent de faire une copie complète (profonde) avec copy.deepcopy() , ce qui pourrait être une overkill, un " normal" copie (superficielle), en utilisant copy.copy() ou dict.copy() , ça devrait suffire. Le dictionnaire conserve une référence à l'objet comme valeur pour une clé. Ainsi, lorsque vous retirez une clé d'un dictionnaire, Cette référence est supprimée, et non l'objet référencé. L'objet lui-même peut être enlevé plus tard automatiquement par le collecteur d'ordures, s'il n'y a pas d'autres références pour lui dans la mémoire. Faire une copie en profondeur nécessite plus de calculs par rapport à la copie superficielle, donc elle diminue la performance du code en faisant la copie, gaspillant la mémoire et fournissant plus de travail au GC, parfois la copie superficielle est suffisante.

cependant, si vous avez des objets mutables comme valeurs de dictionnaire et le plan de les modifier plus tard dans le dictionnaire retourné sans la clé, vous devez faire une copie profonde.

avec une copie superficielle:

def get_dict_wo_key(dictionary, key):
    """Returns a **shallow** copy of the dictionary without a key."""
    _dict = dictionary.copy()
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3, 100], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}

Avec copie en profondeur:

from copy import deepcopy


def get_dict_wo_key(dictionary, key):
    """Returns a **deep** copy of the dictionary without a key."""
    _dict = deepcopy(dictionary)
    _dict.pop(key, None)
    return _dict


d = {"a": [1, 2, 3], "b": 2, "c": 3}
key_to_remove = "c"

new_d = get_dict_wo_key(d, key_to_remove)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3], "b": 2}
new_d["a"].append(100)
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2}
new_d["b"] = 2222
print(d)  # {"a": [1, 2, 3], "b": 2, "c": 3}
print(new_d)  # {"a": [1, 2, 3, 100], "b": 2222}
22
répondu Nikita 2018-01-23 05:15:18
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d

résultat: d = {1: 2, '2': 3}

16
répondu satels 2011-04-30 21:24:48

simplement appeler del d['key'].

Cependant, dans la production, il est toujours une bonne pratique de vérifier si la touche' existe dans d.

if 'key' in d:
    del d['key']
12
répondu Khanh Hua 2015-03-02 13:39:10

Non, il n'y a pas d'autre moyen que

def dictMinus(dct, val):
   copy = dct.copy()
   del copy[val]
   return copy

cependant, créer souvent des copies de dictionnaires légèrement modifiés n'est probablement pas une bonne idée parce qu'il en résultera des demandes de mémoire relativement grandes. Il est généralement préférable d'enregistrer l'ancien dictionnaire (si même nécessaire) et de le modifier.

6
répondu phihag 2011-04-30 21:27:32
>>> def delete_key(dict, key):
...     del dict[key]
...     return dict
... 
>>> test_dict = {'one': 1, 'two' : 2}
>>> print delete_key(test_dict, 'two')
{'one': 1}
>>>

cela ne fait aucune manipulation d'erreur, il suppose que la clé est dans le DCT, vous pourriez vouloir vérifier que d'abord et raise si son pas

5
répondu tMC 2011-04-30 21:26:25

... Comment puis-je supprimer un élément d'un dictionnaire pour retourner une copie (c.-à-d. ne pas modifier l'original)?

A dict est la mauvaise structure de données à utiliser pour cela.

bien sûr, copier le dict et sortir de la copie fonctionne, tout comme construire un nouveau dict avec une compréhension, mais toute cette copie prend du temps-vous avez remplacé une opération à temps constant par une opération à temps linéaire. Et toutes ces copies vivantes prenez à la fois l'espace-l'espace linéaire par copie.

D'autres structures de données, comme tableau de hachage cartographié essais , sont conçus pour exactement ce genre de cas d'utilisation: l'ajout ou la suppression d'un élément renvoie une copie en temps logarithmique, partageant la plupart de son stockage avec l'original . 1

bien sûr, il y a des inconvénients. La Performance est logarithmique plutôt que constante (bien que une grande base, habituellement 32-128). Et, alors que vous pouvez rendre l'API non-Mutant identique à dict , l'API "mutant" est évidemment différente. Et, surtout, il n'y a pas de piles HAMT incluses avec Python. 2

la bibliothèque pyrsistent est une implémentation assez solide des remplacements de dict basés sur HAMT (et divers autres types) pour Python. Il a même un "nifty Evolver API pour transférer le code Mutant existant vers le code persistant aussi facilement que possible. Mais si vous voulez être explicite sur le fait de retourner des copies plutôt que de muter, utilisez-le simplement comme ceci:

>>> from pyrsistent import m
>>> d1 = m(a=1, b=2)
>>> d2 = d1.set('c', 3)
>>> d3 = d1.remove('a')
>>> d1
pmap({'a': 1, 'b': 2})
>>> d2
pmap({'c': 3, 'a': 1, 'b': 2})
>>> d3
pmap({'b': 2})

que d3 = d1.remove('a') est exactement ce que la question demande.

si vous avez des structures de données mutables comme dict et list intégré dans le pmap , vous aurez toujours des problèmes d'Alias-vous ne pouvez corriger cela en allant immuable tout le chemin vers le bas, l'intégration des pmap et de pvector .


1. Les HAMTs sont aussi devenus populaires dans des langages comme Scala, Clojure, Haskell parce qu'ils jouent très bien avec la programmation sans serrure et la mémoire transactionnelle logicielle, mais aucun de ceux-ci n'est très pertinent en Python.

2. En fait, il est un HAMT dans le stdlib, utilisé dans le mise en œuvre de contextvars . le PEP retiré précédemment explique pourquoi. mais c'est un détail caché de mise en œuvre de la Bibliothèque, pas un type de collection publique.

5
répondu abarnert 2018-05-15 01:33:06

Voici une approche de conception de haut niveau:

def eraseElement(d,k):
    if isinstance(d, dict):
        if k in d:
            d.pop(k)
            print(d)
        else:
            print("Cannot find matching key")
    else:
        print("Not able to delete")


exp = {'A':34, 'B':55, 'C':87}
eraseElement(exp, 'C')

je passe le dictionnaire et la clé que je veux dans ma fonction, valide si c'est un dictionnaire et si la clé est ok, et si les deux existent, enlève la valeur du dictionnaire et imprime les restes.

sortie: {'B': 55, 'A': 34}

Espère que ça aide!

4
répondu Bishop 2017-08-15 15:50:44

nice one-liner pour vérifier si la clé est présente, la supprimer, retourner la valeur, ou par défaut:

ret_val = ('key' in body and body.pop('key')) or 5
3
répondu daino3 2017-08-05 20:40:53

ci-dessous code snippet vous aidera certainement, j'ai ajouté des commentaires dans chaque ligne qui vous aideront à comprendre le code.

def execute():
   dic = {'a':1,'b':2}
   dic2 = remove_key_from_dict(dic, 'b')  
   print(dict2)           # {'a': 1}
   print(dict)            # {'a':1,'b':2}

def remove_key_from_dict(dictionary_to_use, key_to_delete):
   copy_of_dict = dict(dictionary_to_use)     # creating clone/copy of the dictionary
   if key_to_delete in copy_of_dict :         # checking given key is present in the dictionary
       del copy_of_dict [key_to_delete]       # deleting the key from the dictionary 
   return copy_of_dict                        # returning the final dictionary

ou vous pouvez également utiliser dict.pop ()

d = {"a": 1, "b": 2}

res = d.pop("c")  # No `KeyError` here
print (res)       # this line will not execute

ou la meilleure approche est de

res = d.pop("c", "key not found")
print (res)   # key not found
print (d)     # {"a": 1, "b": 2}

res = d.pop("b", "key not found")
print (res)   # 2
print (d)     # {"a": 1}
3
répondu Mayur Agarwal 2017-09-30 20:10:01

voici une autre variation utilisant la compréhension de liste:

original_d = {'a': None, 'b': 'Some'}
d = dict((k,v) for k, v in original_d.iteritems() if v)
# result should be {'b': 'Some'}

L'approche est basée sur une réponse de ce post: moyen efficace de retirer les clés à chaînes vides d'un dict

1
répondu BigBlueHat 2017-05-23 12:18:24