Obteniendo 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 dict tiene una clave de value , puede escribir (suponiendo que su lista se llame l )

 [d['value'] for d in l] 

Si falta un value , 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 De esta manera lo veo “más sexy”, pero lo haría usando la lista de comprensión.

Actualización: en caso de que falte ‘valor’ 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 las 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 función única que explícitamente dice lo que quiero lograr:

 >>> import operator, functools >>> get_values = functools.partial(map, operator.itemgetter('value')) >>> get_values(l) ... [] 

Con Python 3, dado que map devuelve un iterador, use list para devolver una lista, por ejemplo, list(map(operator.itemgetter('value'), l)) .

 [x['value'] for x in list_of_dicts] 

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 complican más y necesita comenzar a escribir múltiples cláusulas o comprensiones 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 de dictado y lista anidadas, como JSONPath, DPath y KVC. Y hay bibliotecas agradables 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'] 

Es posible que este no parezca tan simple a primera vista, porque find devuelve objetos coincidentes, 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 '*.[*].value' lugar de una cláusula de comprensión para cada * puede marcar una gran diferencia. Además, JSONPath es una especificación de lenguaje independiente, 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'] 

También puede hacer esto con una combinación de map y lambda , pero la comprensión de la lista se ve más elegante y python.

Para una lista de entrada más pequeña, la comprensión está en camino, 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]:  at 0x7f5774568b10> In[13]: '-'.join(gd) Out[13]: 'apple-banana-cars' 

Aquí hay una comparación de todas las soluciones posibles para mayores aportes.

  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 la razón que dejaré a OP para averiguar.

Una forma muy sencilla de hacerlo es:

 list1=[''] j=0 for i in com_list: if j==0: list1[0]=(i['value']) else: list1.append(i['value']) j+=1 

Salida:

[‘manzana’, ‘plátano’, ‘coches’]

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))))