Tengo un dict
que tiene un montón de entradas. Solo estoy interesado en unos pocos de ellos. ¿Hay una manera fácil de eliminar a todos los demás?
Tengo un dict
que tiene un montón de entradas. Solo estoy interesado en unos pocos de ellos. ¿Hay una manera fácil de eliminar a todos los demás?
Respuestas:
Construyendo un nuevo dict:
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }
Utiliza la comprensión del diccionario.
Si utiliza una versión que carece de ellas (es decir, Python 2.6 y versiones anteriores), hágalo dict((your_key, old_dict[your_key]) for ...)
. Es lo mismo, aunque más feo.
Tenga en cuenta que esto, a diferencia de la versión de jnnnnn, tiene un rendimiento estable (depende solo del número de your_keys) para old_dict
s de cualquier tamaño. Ambos en términos de velocidad y memoria. Como se trata de una expresión generadora, procesa un elemento a la vez y no examina todos los elementos de old_dict.
Eliminar todo en su lugar:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
old_dict
indica un error en otro lugar, y en ese caso prefiero un error a resultados silenciosamente incorrectos.
Ligeramente más elegante comprensión dict:
foodict = {k: v for k, v in mydict.items() if k.startswith('foo')}
mydict.iteritems()
lugar. .items()
crea otra lista
Aquí hay un ejemplo en Python 2.6:
>>> a = {1:1, 2:2, 3:3}
>>> dict((key,value) for key, value in a.iteritems() if key == 1)
{1: 1}
La parte de filtrado es la if
declaración.
Este método es más lento que la respuesta de delnan si solo desea seleccionar algunas de las muchas teclas.
if key in ('x','y','z')
, supongo.
Puede hacerlo con la función de proyecto de mi biblioteca funcy :
from funcy import project
small_dict = project(big_dict, keys)
También eche un vistazo a select_keys .
Código 1:
dict = { key: key * 10 for key in range(0, 100) }
d1 = {}
for key, value in dict.items():
if key % 2 == 0:
d1[key] = value
Código 2:
dict = { key: key * 10 for key in range(0, 100) }
d2 = {key: value for key, value in dict.items() if key % 2 == 0}
Código 3:
dict = { key: key * 10 for key in range(0, 100) }
d3 = { key: dict[key] for key in dict.keys() if key % 2 == 0}
Todas las partes del rendimiento del código se miden con timeit usando number = 1000, y se recopilan 1000 veces para cada fragmento de código.
Para Python 3.6, el rendimiento de tres formas de filtrar claves de dictado es casi el mismo. Para python 2.7, el código 3 es un poco más rápido.
Este liner lambda debería funcionar:
dictfilt = lambda x, y: dict([ (i,x[i]) for i in x if i in set(y) ])
Aquí hay un ejemplo:
my_dict = {"a":1,"b":2,"c":3,"d":4}
wanted_keys = ("c","d")
# run it
In [10]: dictfilt(my_dict, wanted_keys)
Out[10]: {'c': 3, 'd': 4}
Es una comprensión básica de la lista que itera sobre sus claves de dictado (i en x) y genera una lista de pares de tuplas (clave, valor) si la clave vive en la lista de claves deseada (y). Un dict () envuelve todo para que salga como un objeto dict.
set
for wanted_keys
, pero por lo demás se ve bien.
dictfilt({'x':['wefwef',52],'y':['iuefiuef','efefij'],'z':['oiejf','iejf']}, ('x','z'))
vuelve {'x': ['wefwef', 52], 'z': ['oiejf', 'iejf']}
como estaba previsto.
dict={'0':[1,3], '1':[0,2,4], '2':[1,4]}
y el resultado fue {}
, que supuse que era un dict en blanco.
foo = {'0':[1,3], '1':[0,2,4], '2':[1,4]}; dictfilt(foo,('0','2'))
obtengo: {'0': [1, 3], '2': [1, 4]}
cuál es el resultado esperado
Dado su diccionario original orig
y el conjunto de entradas que le interesan keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
que no es tan bueno como la respuesta de delnan, pero debería funcionar en todas las versiones de Python de interés. Sin embargo, es frágil para cada elemento keys
existente en su diccionario original.
Basado en la respuesta aceptada por delnan.
¿Qué pasa si una de sus claves deseadas no está en el old_dict? La solución delnan arrojará una excepción KeyError que puede atrapar. Si eso no es lo que necesitas, tal vez quieras:
solo incluya claves que se eliminen tanto en old_dict como en su conjunto de wanted_keys.
old_dict = {'name':"Foobar", 'baz':42}
wanted_keys = ['name', 'age']
new_dict = {k: old_dict[k] for k in set(wanted_keys) & set(old_dict.keys())}
>>> new_dict
{'name': 'Foobar'}
tiene un valor predeterminado para las claves que no está establecido en old_dict.
default = None
new_dict = {k: old_dict[k] if k in old_dict else default for k in wanted_keys}
>>> new_dict
{'age': None, 'name': 'Foobar'}
{k: old_dict.get(k, default) for k in ...}
Esta función hará el truco:
def include_keys(dictionary, keys):
"""Filters a dict by only including certain keys."""
key_set = set(keys) & set(dictionary.keys())
return {key: dictionary[key] for key in key_set}
Al igual que la versión de delnan, esta utiliza la comprensión del diccionario y tiene un rendimiento estable para diccionarios grandes (depende solo de la cantidad de claves que permita y no de la cantidad total de claves en el diccionario).
Y al igual que la versión de MyGGan, esta permite que su lista de claves incluya claves que pueden no existir en el diccionario.
Y como beneficio adicional, aquí está el inverso, donde puede crear un diccionario excluyendo ciertas claves en el original:
def exclude_keys(dictionary, keys):
"""Filters a dict by excluding certain keys."""
key_set = set(dictionary.keys()) - set(keys)
return {key: dictionary[key] for key in key_set}
Tenga en cuenta que, a diferencia de la versión de delnan, la operación no se realiza en su lugar, por lo que el rendimiento está relacionado con la cantidad de teclas en el diccionario. Sin embargo, la ventaja de esto es que la función no modificará el diccionario proporcionado.
Editar: se agregó una función separada para excluir ciertas teclas de un dict.
invert
implica que keys
se mantiene el argumento o que keys
se rechaza el argumento?", ¿Cuántos de ellos estarían de acuerdo?
Si queremos hacer un nuevo diccionario con las claves seleccionadas eliminadas, podemos hacer uso de la comprensión del diccionario.
Por ejemplo:
d = {
'a' : 1,
'b' : 2,
'c' : 3
}
x = {key:d[key] for key in d.keys() - {'c', 'e'}} # Python 3
y = {key:d[key] for key in set(d.keys()) - {'c', 'e'}} # Python 2.*
# x is {'a': 1, 'b': 2}
# y is {'a': 1, 'b': 2}
Otra opción:
content = dict(k1='foo', k2='nope', k3='bar')
selection = ['k1', 'k3']
filtered = filter(lambda i: i[0] in selection, content.items())
Pero obtienes un list
(Python 2) o un iterador (Python 3) devuelto por filter()
, no a dict
.
filtered
en dict
y obtiene nuevamente el diccionario!
Aquí hay otro método simple que se utiliza del
en un revestimiento:
for key in e_keys: del your_dict[key]
e_keys
es la lista de las claves que se excluirán. Actualizará su dict en lugar de darle uno nuevo.
Si desea un nuevo dict de salida, haga una copia del dict antes de eliminar:
new_dict = your_dict.copy() #Making copy of dict
for key in e_keys: del new_dict[key]
Podrías usar python-benedict
, es una subclase dict.
Instalación: pip install python-benedict
from benedict import benedict
dict_you_want = benedict(your_dict).subset(keys=['firstname', 'lastname', 'email'])
Es de código abierto en GitHub: https://github.com/fabiocaccamo/python-benedict
Descargo de responsabilidad: soy el autor de esta biblioteca.