¿Hay alguna forma de eliminar un elemento de un diccionario en Python?
Además, ¿cómo puedo eliminar un elemento de un diccionario para devolver una copia (es decir, sin modificar el original)?
python
dictionary
del
richzilla
fuente
fuente
pop
método cambia el diccionario en el lugar . Por lo tanto, altera la referencia al diccionario que se pasó de la persona que llama a la "función auxiliar". Por lo tanto, la "función auxiliar" no necesita devolver nada, ya que la referencia original al diccionario en la persona que llama ya estará alterada. No asigne el retorno dedict.pop()
a nada si no lo necesita. EG:do stuff with my_dict; my_dict.pop(my_key, None); do more stuff with my_dict # now doesn't have my_key
. Úselodeepcopy(my_dict)
si es necesario.d.pop()
, arreglé el título para hacer la pregunta especificada en los detalles.d.pop(key)
. Pero si algo modifica alguna vez la copia superficial, tiene un problema bien conocido con alias . Ayuda si nos cuenta el contexto más amplio. (¿Algo más está modificando los valores dict? ¿Estás tratando de iterar destructivamente sobre una lista? Si no, ¿qué?)Respuestas:
La
del
declaración elimina un elemento:Sin embargo, 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 nuevo diccionario, haga una copia del diccionario:
El
dict()
constructor hace una copia superficial . Para hacer una copia profunda, vea elcopy
módulo .Tenga en cuenta que hacer una copia para cada dict
del
/ asignación / etc. significa que vas del tiempo constante al tiempo lineal, y también estás usando el espacio lineal. Para pequeños dictados, esto no es un problema. Pero si planea hacer muchas copias de grandes dictados, probablemente desee una estructura de datos diferente, como un HAMT (como se describe en esta respuesta ).fuente
dict
mientras lo recorre, le dará un error:RuntimeError: dictionary changed size during iteration
pop
método que de hecho hace lo mismo? ¿No es más pitónico? (siendo el método dict, no una palabra reservada especial)?pop
Muta el diccionario.Si desea conservar el original, simplemente puede copiarlo.
fuente
pop
devuelve el valor que fue 'reventado', lo que le permite usar este valor por cualquier otra razón. Si no es más "Pythonic", diría que parece mejor, seguro :). No es un dict, pero funciona de la misma manera para ambos: github.com/ivanlmj/python-prototypes/blob/master/3.4/…pop
se le puede proporcionar un valor predeterminado que se devolverá cuando falta una clave en dict. Es bueno cuando necesita eliminar algunas claves, pero algunas pueden faltar;del
tiraríaKeyError
en tal caso.Creo que su solución es la mejor manera de hacerlo. Pero si desea otra solución, puede crear un nuevo diccionario utilizando las claves del diccionario anterior sin incluir la clave especificada, como esta:
fuente
{i:a[i] for i in a if i not in [0, 1, 2]}
si desean eliminar varios elementos.{k:v for k,v in a.items() if k != 0}
, creo.**kwargs
,some_function(**{k:v for k,v in some_dict.items() if k not 'some_key'})
La declaración del es lo que estás buscando. Si tiene un diccionario llamado foo con una clave llamada 'bar', puede eliminar 'bar' de foo de esta manera:
Tenga en cuenta que esto modifica permanentemente el diccionario que se está utilizando. Si desea conservar el diccionario original, deberá crear una copia de antemano:
La
dict
llamada hace una copia superficial. Si quieres una copia profunda, úsalacopy.deepcopy
.Aquí hay un método que puede copiar y pegar, para su conveniencia:
fuente
>>>
se usa a menudo en los ejemplos de python? Sí, python-doc contiene muchas de esas cosas. Pero dicho código no es conveniente para copiar . Estoy confundido ...>>>
imita la notación de escucha de pitón en el modo CLI>>>
. Sí, es de estilo REPL, pero hablemos con franqueza: el único hombre había escrito esta muestra, y 1000 lo han leído. Creo que sería genial escribir ejemplos de la manera que permite copiar y ejecutar fácilmente. No me gusta eliminar estos corchetes angulares a mano. O copie línea por línea ... Así que no entiendo: ¿por qué estos ángulos siguen ahí))) ¿Puede ser que no sé algo?Hay muchas respuestas agradables, pero quiero enfatizar una cosa.
Puede usar tanto el
dict.pop()
método como unadel
declaración más genérica para eliminar elementos de un diccionario. Ambos mutan el diccionario original, por lo que debe hacer una copia (consulte los detalles a continuación).Y ambos aparecerán
KeyError
si la clave que les está proporcionando no está presente en el diccionario:y
Tienes que ocuparte de esto:
capturando la excepción:
y
realizando una verificación:
y
pero
pop()
también hay una forma mucho más concisa: proporcione el valor de retorno predeterminado:A menos que utilice
pop()
para obtener el valor de una clave que se eliminará, puede proporcionar cualquier cosa, no necesariaNone
. Aunque podría ser que usarlodel
conin
check es un poco más rápido debido a quepop()
es una función con sus propias complicaciones que causan sobrecarga. Por lo general, no es el caso, por lo quepop()
con el valor predeterminado es lo suficientemente bueno.En cuanto a la pregunta principal, tendrá que hacer una copia de su diccionario, 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()
, que podría ser una exageración, una copia "normal" (superficial), usandocopy.copy()
odict.copy()
, podría ser suficiente. El diccionario mantiene una referencia al objeto como valor para una clave. Entonces, cuando elimina una clave de un diccionario, se elimina esta referencia, no el objeto al que se hace referencia. El objeto en sí puede ser eliminado más tarde automáticamente por el recolector de basura, 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 hacer 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 hacer una copia profunda.
Con copia superficial:
Con copia profunda:
fuente
A
dict
es la estructura de datos incorrecta para usar para esto.Claro, copiar el dict y el estallido de la copia funciona, y también lo hace construir un nuevo dict con una comprensión, pero toda esa copia lleva tiempo: ha reemplazado una operación de tiempo constante por una de tiempo lineal. Y todas esas copias vivas a la vez ocupan espacio: espacio lineal por copia.
Otras estructuras de datos, como los intentos de mapeo de matriz hash , están diseñados para este tipo de caso de uso: agregar o eliminar un elemento devuelve una copia en tiempo logarítmico, compartiendo la mayor parte de su almacenamiento con el original . 1
Por supuesto que hay algunos inconvenientes. El rendimiento es logarítmico en lugar de constante (aunque con una base grande, generalmente 32-128). Y, si bien puede hacer que la API no mutante sea idéntica
dict
, la API "mutante" es obviamente diferente. Y, sobre todo, no hay baterías HAMT incluidas con Python. 2La
pyrsistent
biblioteca es una implementación bastante sólida de reemplazos dict basados en HAMT (y varios otros tipos) para Python. Incluso tiene una ingeniosa API de evolución para portar código mutante existente a código persistente de la manera más fluida posible. Pero si desea ser explícito acerca de devolver copias en lugar de mutar, simplemente utilícelo de esta manera:Eso
d3 = d1.remove('a')
es exactamente lo que pide la pregunta.Si tiene estructuras de datos mutables como
dict
elist
incrustadas en elpmap
, aún tendrá problemas de alias: solo puede solucionarlo si se vuelve inmutable hasta el fondo, incrustandopmap
sypvector
s.1. Los HAMT también se han vuelto populares en lenguajes como Scala, Clojure, Haskell porque juegan muy bien con la programación sin bloqueo y la memoria transaccional de software, pero ninguno de los dos es muy relevante en Python.
2. De hecho, no es un HAMT en el stdlib, que se utiliza en la ejecución de
contextvars
. El PEP retirado anteriormente explica por qué. Pero este es un detalle de implementación oculto de la biblioteca, no un tipo de colección pública.fuente
Resultado:
d = {1: 2, '2': 3}
fuente
Simplemente llame a del d ['clave'].
Sin embargo, en producción, siempre es una buena práctica verificar si existe 'clave' en d.
fuente
try-except
bloque. Al menos, esta será una operación atómica;)d.pop('key', None)
, úsalo, es una línea. Pero la pregunta real era sobre obtener el diccionario sin una clave, y no sobre modificar el dict. Entonces las comprensiones - es una buena opción aquí;)No, no hay otra manera que
Sin embargo, a menudo crear copias de diccionarios ligeramente alterados probablemente no sea una buena idea porque generará demandas de memoria relativamente grandes. Por lo general, es mejor registrar el diccionario antiguo (si es necesario) y luego modificarlo.
fuente
fuente
esto no hace ningún manejo de errores, asume que la clave está en el dict, es posible que desee verificar eso primero y
raise
si nofuente
del test_dict[key]
?Aquí un enfoque de diseño de nivel superior:
Estoy pasando el diccionario y la clave que quiero a mi función, valida si es un diccionario y si la clave está bien, y si ambos existen, elimina el valor del diccionario e imprime los sobrantes.
Salida:
{'B': 55, 'A': 34}
¡Espero que ayude!
fuente
A continuación, el fragmento de código lo ayudará definitivamente, he agregado comentarios en cada línea que lo ayudarán a comprender el código.
o también puedes usar dict.pop ()
o el mejor enfoque es
fuente
Aquí hay otra variación usando la comprensión de la lista:
El enfoque se basa en una respuesta de esta publicación: forma eficiente de eliminar claves con cadenas vacías de un dict
fuente
if v
aif k is not 'a'
respuestas el op. Pero no creo que sea una forma eficiente, esto elimina el elemento en O (n) en lugar de O (log n) como lo hace pop o del.El siguiente código hará una copia de dict
species
y eliminará elementos que no están entrans_HI
fuente