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)?
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 ).
pop
mute le dictionnaire.
>>>lol = {"hello":"gdbye"}
>>>lol.pop("hello")
'gdbye'
>>> lol
{}
Si vous voulez garder l'original, vous pouvez simplement copier.
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'}
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
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}
d = {1: 2, '2': 3, 5: 7}
del d[5]
print 'd = ', d
résultat: d = {1: 2, '2': 3}
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']
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.
>>> 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
... 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.
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!
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
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}
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