resueltos - lista dentro de un diccionario python
Mapeo de valores en un diccionario python (6)
Dado un diccionario { k1: v1, k2: v2 ... }
Quiero obtener { k1: f(v1), k2: f(v2) ... }
siempre que pase una función f
.
¿Hay alguna de esas funciones integradas? O tengo que hacer
dict([(k, f(v)) for (k, v) in my_dictionary.iteritems()])
Idealmente solo escribiría
my_dictionary.map_values(f)
o
my_dictionary.mutate_values_with(f)
Es decir, no me importa si el diccionario original está mutado o si se crea una copia.
Acabo de cruzar este caso de uso. Implementé la respuesta de gens , agregando un enfoque recursivo para manejar valores que también son dicts:
def mutate_dict_in_place(f, d):
for k, v in d.iteritems():
if isinstance(v, dict):
mutate_dict_in_place(f, v)
else:
d[k] = f(v)
# Exemple handy usage
def utf8_everywhere(d):
mutate_dict_in_place((
lambda value:
value.decode(''utf-8'')
if isinstance(value, bytes)
else value
),
d
)
my_dict = {''a'': b''byte1'', ''b'': {''c'': b''byte2'', ''d'': b''byte3''}}
utf8_everywhere(my_dict)
print(my_dict)
Esto puede ser útil cuando se trata de archivos json o yaml que codifican cadenas como bytes en Python 2
Estas herramientas son geniales para este tipo de lógica simple pero repetitiva.
http://toolz.readthedocs.org/en/latest/api.html#toolz.dicttoolz.valmap
Ponte en el lugar donde quieres estar.
import toolz
def f(x):
return x+1
toolz.valmap(f, my_list)
No hay tal función; la forma más fácil de hacer esto es usar una comprensión dict:
my_dictionary = {k: f(v) for k, v in my_dictionary.items()}
En python 2.7, use el método .iteritems()
lugar de .items()
para guardar la memoria. La sintaxis de comprensión dict no se introdujo hasta que Python 2.7.
Tenga en cuenta que tampoco existe dicho método en las listas; Tendría que usar una función de comprensión de lista o map()
.
Como tal, podría usar la función map()
para procesar su dict también:
my_dictionary = dict(map(lambda kv: (kv[0], f(kv[1])), my_dictionary.iteritems()))
pero eso no es tan legible, de verdad.
Puede hacer esto en su lugar, en lugar de crear un nuevo diccionario, que puede ser preferible para diccionarios grandes (si no necesita una copia).
def mutate_dict(f,d):
for k, v in d.iteritems():
d[k] = f(v)
my_dictionary = {''a'':1, ''b'':2}
mutate_dict(lambda x: x+1, my_dictionary)
resultados en my_dictionary
contienen:
{''a'': 2, ''b'': 3}
Si bien mi respuesta original olvidó el punto (al tratar de resolver este problema con la solución de acceso a la clave en fábrica de defaultdict ), lo he reelaborado para proponer una solución real a la presente pregunta.
Aquí está:
class walkableDict(dict):
def walk(self, callback):
try:
for key in self:
self[key] = callback(self[key])
except TypeError:
return False
return True
Uso:
>>> d = walkableDict({ k1: v1, k2: v2 ... })
>>> d.walk(f)
La idea es subclasificar el dict original para darle la funcionalidad deseada: "mapear" una función sobre todos los valores.
El punto positivo es que este diccionario se puede utilizar para almacenar los datos originales como si fuera un dict
, mientras se transforman los datos bajo petición con una devolución de llamada.
Por supuesto, siéntase libre de nombrar la clase y la función de la manera que desee (el nombre elegido en esta respuesta está inspirado en la función array_walk()
PHP).
Nota: Ni el try
- except
bloqueo ni las declaraciones de return
son obligatorias para la funcionalidad, están ahí para imitar aún más el comportamiento del array_walk
de PHP.