Obtener una lista de valores de una lista de dictados
Tengo una lista de dictados como este:
[{'value': 'apple', 'blah': 2},
{'value': 'banana', 'blah': 3} ,
{'value': 'cars', 'blah': 4}]
Quiero['apple', 'banana', 'cars']
¿Cuál es la mejor manera de hacer esto?
Suponiendo que cada dictado tenga una value
clave, puede escribir (suponiendo que su lista se llame l
)
[d['value'] for d in l]
Si value
falta, puedes usar
[d['value'] for d in l if 'value' in d]
Aquí hay otra forma de hacerlo usando las funciones map() y lambda:
>>> map(lambda d: d['value'], l)
donde l es la lista. Veo esta manera "más sexy", pero lo haría usando la lista de comprensión.
Actualización: en caso de que falte ese 'valor' como clave, utilice:
>>> map(lambda d: d.get('value', 'default value'), l)
Actualización: Tampoco soy un gran admirador de las lambdas, prefiero nombrar las cosas... así es como lo haría con eso en mente:
>>> import operator
>>> get_value = operator.itemgetter('value')
>>> map(get_value, l)
Incluso iría más allá y crearía una función única que diga explícitamente lo que quiero lograr:
>>> import operator, functools
>>> get_value = operator.itemgetter('value')
>>> get_values = functools.partial(map, get_value)
>>> get_values(l)
... [<list of values>]
Con Python 3, dado que map
devuelve un iterador, utilícelo list
para devolver una lista, por ejemplo list(map(operator.itemgetter('value'), l))
.
[x['value'] for x in list_of_dicts]
Creo que tan simple como lo siguiente te dará lo que estás buscando.
In[5]: ll = [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}]
In[6]: ld = [d.get('value', None) for d in ll]
In[7]: ld
Out[7]: ['apple', 'banana', 'cars']
Puedes hacer esto con una combinación de map
y lambda
también, pero la comprensión de la lista parece más elegante y pitónica.
Para una lista de entrada más pequeña, la comprensión es un camino por recorrer, pero si la entrada es realmente grande, entonces supongo que los generadores son la forma ideal.
In[11]: gd = (d.get('value', None) for d in ll)
In[12]: gd
Out[12]: <generator object <genexpr> at 0x7f5774568b10>
In[13]: '-'.join(gd)
Out[13]: 'apple-banana-cars'
Aquí hay una comparación de todas las soluciones posibles para una mayor entrada.
In[2]: l = [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3} , {'value': 'cars', 'blah':4}] * 9000000
In[3]: def gen_version():
...: for i in l:
...: yield i.get('value', None)
...:
In[4]: def list_comp_verison():
...: return [i.get('value', None) for i in l]
...:
In[5]: def list_verison():
...: ll = []
...: for i in l:
...: ll.append(i.get('value', None))
...: return ll
In[10]: def map_lambda_version():
...: m = map(lambda i:i.get('value', None), l)
...: return m
...:
In[11]: %timeit gen_version()
172 ns ± 0.393 ns per loop (mean ± std. dev. of 7 runs, 10000000 loops each)
In[12]: %timeit map_lambda_version()
203 ns ± 2.31 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
In[13]: %timeit list_comp_verison()
1.61 s ± 20.4 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
In[14]: %timeit list_verison()
2.29 s ± 4.58 ms per loop (mean ± std. dev. of 7 runs, 1 loop each)
Como puede ver, los generadores son una mejor solución en comparación con los demás, el mapa también es más lento en comparación con el generador, por lo que dejaré que OP lo resuelva.