dictionaries - dict filter python
¿El filtro dict para contener solamente ciertas claves? (11)
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 sentencia if
.
Este método es más lento que la respuesta de Delnan si solo desea seleccionar algunas de las muchas claves.
Tengo un dict
que tiene un montón de entradas. Sólo estoy interesado en unos pocos seleccionados. ¿Hay una manera fácil de podar todos los demás?
Basado en la respuesta aceptada por delnan.
¿Qué pasa si una de sus claves buscadas no está en el old_dict? La solución de delnan lanzará una excepción KeyError que puede capturar. Si eso no es lo que necesitas quizás quieras:
solo incluye claves que exista tanto en el old_dict como en tu 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án establecidas 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''}
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 piezas del rendimiento del código se miden con timeit usando number = 1000, y se recopilan 1000 veces para cada pieza de código.
Para Python 3.6, el rendimiento de tres formas de filtrado de claves de dictado es casi el mismo. Para Python 2.7 el código 3 es ligeramente más rápido.
Construyendo un nuevo dictado:
dict_you_want = { your_key: old_dict[your_key] for your_key in your_keys }
Utiliza la comprensión del diccionario.
Si usas una versión que no los tiene (es decir, Python 2.6 y anteriores), haz que 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 teclas your_) para old_dict
s de cualquier tamaño. Tanto en términos de velocidad como de memoria. Como esta es una expresión generadora, procesa un elemento a la vez y no examina todos los elementos de old_dict.
Eliminando todo en el lugar:
unwanted = set(keys) - set(your_dict)
for unwanted_key in unwanted: del your_dict[unwanted_key]
Dado el origen de su diccionario original y el conjunto de entradas que le interesan en las keys
:
filtered = dict(zip(keys, [orig[k] for k in keys]))
que no es tan agradable 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 de las keys
existentes en su diccionario original.
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, ésta utiliza la comprensión del diccionario y tiene un rendimiento estable para los diccionarios grandes (depende solo de la cantidad de claves que usted permita, y no del número 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á la inversa, donde puede crear un diccionario al excluir 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 claves en el diccionario. Sin embargo, la ventaja de esto es que la función no modificará el diccionario proporcionado.
Edición: Se agregó una función separada para excluir ciertas teclas de un dict.
Este forro 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 lista de comprensión básica que recorre las teclas dict (i en x) y genera una lista de pares de tuplas (clave, valor) si la clave se encuentra en la lista de claves deseada (y). Un dict () envuelve todo para dar salida como un objeto dict.
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 una list
(Python 2) o un iterador (Python 3) devuelto por filter()
, no un dict
.
Puedes hacer eso con la función de project de mi librería funcy :
from funcy import project
small_dict = project(big_dict, keys)
También eche un vistazo a select_keys .
Un poco más elegante dict comprensión:
foodict = {k: v for k, v in mydict.items() if k.startswith(''foo'')}
Forma corta:
[s.pop(k) for k in list(s.keys()) if k not in keep]
Como la mayoría de las respuestas sugieren para mantener la concisión, tenemos que crear un objeto duplicado, ya sea una list
o un dict
. Éste crea una list
eliminación pero elimina las claves en el dict
original.