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?
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?
Respuestas:
Suponiendo que cada dict tiene una value
clave, puede escribir (suponiendo que su lista tenga un nombre l
)
[d['value'] for d in l]
Si value
puede faltar, puede 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 de esta manera "más sexy", pero lo haría usando la lista de comprensión.
Actualización: en caso de que ese 'valor' pueda faltar como uso clave:
>>> map(lambda d: d.get('value', 'default value'), l)
Actualización: tampoco soy un gran fanático de las lambdas, prefiero nombrar cosas ... así es como lo haría con eso en mente:
>>> import operator
>>> map(operator.itemgetter('value'), l)
Incluso iría más allá y crearía una única función que diga explícitamente lo que quiero lograr:
>>> import operator, functools
>>> get_values = functools.partial(map, operator.itemgetter('value'))
>>> get_values(l)
... [<list of values>]
Con Python 3, dado que map
devuelve un iterador, use list
para devolver una lista, por ejemplo list(map(operator.itemgetter('value'), l))
.
map
, use operator.itemgetter('value')
, no a lambda
.
[x['value'] for x in list_of_dicts]
getkey
... ¿quieres decir d.get('value')
? Eso sería lo mismo que la comprensión de la segunda lista de @ isbadawi, no la de Michal.
Para un caso muy simple como este, una comprensión, como en la respuesta de Ismail Badawi, es definitivamente el camino a seguir.
Pero cuando las cosas se vuelven más complicadas y necesita comenzar a escribir comprensiones de múltiples cláusulas o anidadas con expresiones complejas, vale la pena buscar otras alternativas. Hay algunas formas diferentes (casi) estándar para especificar búsquedas de estilo XPath en estructuras anidadas de dict-and-list, como JSONPath, DPath y KVC. Y hay buenas bibliotecas en PyPI para ellos.
Aquí hay un ejemplo con la biblioteca llamada dpath
, que muestra cómo puede simplificar algo un poco más complicado:
>>> dd = {
... 'fruits': [{'value': 'apple', 'blah': 2}, {'value': 'banana', 'blah': 3}],
... 'vehicles': [{'value': 'cars', 'blah':4}]}
>>> {key: [{'value': d['value']} for d in value] for key, value in dd.items()}
{'fruits': [{'value': 'apple'}, {'value': 'banana'}],
'vehicles': [{'value': 'cars'}]}
>>> dpath.util.search(dd, '*/*/value')
{'fruits': [{'value': 'apple'}, {'value': 'banana'}],
'vehicles': [{'value': 'cars'}]}
O, usando jsonpath-ng
:
>>> [d['value'] for key, value in dd.items() for d in value]
['apple', 'banana', 'cars']
>>> [m.value for m in jsonpath_ng.parse('*.[*].value').find(dd)]
['apple', 'banana', 'cars']
A primera vista, este puede no parecer tan simple, porque find
devuelve objetos de coincidencia, que incluyen todo tipo de cosas además del valor coincidente, como una ruta directamente a cada elemento. Pero para expresiones más complejas, poder especificar una ruta como en '*.[*].value'
lugar de una cláusula de comprensión para cada una *
puede hacer una gran diferencia. Además, JSONPath es una especificación independiente del idioma, e incluso hay probadores en línea que pueden ser muy útiles para la depuración.
Creo que tan simple como a continuación le daría lo que está 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']
Puede hacer esto con una combinación de map
y lambda
también, pero la comprensión de la lista se ve más elegante y pitónica.
Para una lista de entrada más pequeña, la comprensión es un camino a seguir, pero si la entrada es realmente grande, 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 descubra.
Sigue el ejemplo --
songs = [
{"title": "happy birthday", "playcount": 4},
{"title": "AC/DC", "playcount": 2},
{"title": "Billie Jean", "playcount": 6},
{"title": "Human Touch", "playcount": 3}
]
print("===========================")
print(f'Songs --> {songs} \n')
title = list(map(lambda x : x['title'], songs))
print(f'Print Title --> {title}')
playcount = list(map(lambda x : x['playcount'], songs))
print(f'Print Playcount --> {playcount}')
print (f'Print Sorted playcount --> {sorted(playcount)}')
# Aliter -
print(sorted(list(map(lambda x: x['playcount'],songs))))
¿Obtener valores clave de la lista de diccionarios en Python?
Ex:
data =
[{'obj1':[{'cpu_percentage':'15%','ram':3,'memory_percentage':'66%'}]},
{'obj2': [{'cpu_percentage':'0','ram':4,'memory_percentage':'35%'}]}]
para d en datos:
for key,value in d.items():
z ={key: {'cpu_percentage': d['cpu_percentage'],'memory_percentage': d['memory_percentage']} for d in value}
print(z)
Salida:
{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}