Eliminar un elemento de un diccionario

Resuelto richzilla asked hace 13 años • 19 respuestas

¿Cómo elimino un elemento de un diccionario en Python?

Sin modificar el diccionario original, ¿cómo obtengo otro diccionario con el elemento eliminado?


Consulte también ¿Cómo puedo eliminar una clave de un diccionario de Python? para el problema específico de eliminar un elemento (por clave) que quizás aún no esté presente.

richzilla avatar May 01 '11 04:05 richzilla
Aceptado

La deldeclaración elimina un elemento:

del d[key]

Tenga en cuenta que esto muta el diccionario existente, por lo que el contenido del diccionario cambia para cualquier otra persona que tenga una referencia a la misma instancia. Para devolver un diccionario nuevo , haga una copia del diccionario:

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

El dict()constructor hace una copia superficial . Para hacer una copia profunda, consulte el copymódulo .


Tenga en cuenta que hacer una copia para cada dict del/assignment/etc. significa que vas de un tiempo constante a un tiempo lineal, y también estás usando un espacio lineal. Para dictados pequeños, esto no es un problema. Pero si planea hacer muchas copias de dictados grandes, probablemente desee una estructura de datos diferente, como un HAMT (como se describe en esta respuesta ).

Greg Hewgill avatar Apr 30 '2011 21:04 Greg Hewgill

popmuta el diccionario.

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

Si desea conservar el original, puede copiarlo.

Crystal avatar Mar 21 '2014 16:03 Crystal

Creo que tu solución es la mejor manera de hacerlo. Pero si desea otra solución, puede crear un nuevo diccionario usando las claves del diccionario anterior sin incluir la clave especificada, como esta:

>>> 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'}
utdemir avatar Apr 30 '2011 21:04 utdemir

Hay muchas respuestas buenas, pero quiero enfatizar una cosa.

Puede utilizar tanto el método como una declaracióndict.pop() más genérica para eliminar elementos de un diccionario. Ambos mutan el diccionario original, por lo que es necesario hacer una copia (consulte los detalles a continuación).del

Y ambos generarán un mensaje KeyErrorsi la clave que les estás proporcionando no está presente en el diccionario:

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

y

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

Tienes que cuidar esto:

capturando la excepción:

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)

y

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)

realizando una verificación:

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

y

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

pero pop()también hay una forma mucho más concisa: proporcionar el valor de retorno predeterminado:

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

A menos que utilice pop()para obtener el valor de una clave que se elimina, puede proporcionar cualquier cosa que no sea necesaria None. Aunque podría ser que usar delwith incheck sea un poco más rápido debido a que pop()es una función con sus propias complicaciones que causan gastos generales. Normalmente no es el caso, por lo pop()que el valor predeterminado es suficiente.


En cuanto a la pregunta principal, tendrás que hacer una copia de tu diccionario, para guardar el diccionario original y tener uno nuevo sin quitar la clave.

Algunas otras personas aquí sugieren hacer una copia completa (profunda) con copy.deepcopy(), lo que podría ser excesivo, una copia "normal" (superficial), usando copy.copy()o dict.copy(), podría ser suficiente. El diccionario mantiene una referencia al objeto como valor de una clave. Entonces, cuando elimina una clave de un diccionario, se elimina esta referencia, no el objeto al que se hace referencia. El recolector de basura puede eliminar automáticamente el objeto en sí más tarde, si no hay otras referencias para él en la memoria. Hacer una copia profunda requiere más cálculos en comparación con una copia superficial, por lo que disminuye el rendimiento del código al realizar la copia, desperdiciando memoria y proporcionando más trabajo al GC; a veces, una copia superficial es suficiente.

Sin embargo, si tiene objetos mutables como valores de diccionario y planea modificarlos más adelante en el diccionario devuelto sin la clave, debe realizar una copia profunda.

Con copia superficial:

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}

Con copia profunda:

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}
Nikita avatar Sep 21 '2017 19:09 Nikita

La declaración del es lo que estás buscando. Si tienes un diccionario llamado foo con una clave llamada 'bar', puedes eliminar 'bar' de foo de esta manera:

del foo['bar']

Tenga en cuenta que esto modifica permanentemente el diccionario en el que se está operando. Si desea conservar el diccionario original, deberá crear una copia previamente:

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

La dictllamada hace una copia superficial. Si desea una copia profunda, utilice copy.deepcopy.

Aquí tienes un método que puedes copiar y pegar, para tu comodidad:

def minus_key(key, dictionary):
    shallow_copy = dict(dictionary)
    del shallow_copy[key]
    return shallow_copy
arussell84 avatar Apr 30 '2011 21:04 arussell84