Ho un elenco di dicts come questo:
[{'value': 'apple', 'blah': 2},
{'value': 'banana', 'blah': 3} ,
{'value': 'cars', 'blah': 4}]
Voglio ['apple', 'banana', 'cars']
qual'è il miglior modo per farlo?
Ho un elenco di dicts come questo:
[{'value': 'apple', 'blah': 2},
{'value': 'banana', 'blah': 3} ,
{'value': 'cars', 'blah': 4}]
Voglio ['apple', 'banana', 'cars']
qual'è il miglior modo per farlo?
Risposte:
Supponendo che ogni dict abbia una value
chiave, puoi scrivere (supponendo che il tuo elenco sia chiamato l
)
[d['value'] for d in l]
Se value
potrebbe mancare, è possibile utilizzare
[d['value'] for d in l if 'value' in d]
[d.value for d in l]
ringraziamento :)
Ecco un altro modo per farlo usando le funzioni map () e lambda:
>>> map(lambda d: d['value'], l)
dove l è l'elenco. Vedo in questo modo "più sexy", ma lo farei usando la comprensione della lista.
Aggiornamento: nel caso in cui il "valore" potrebbe mancare come chiave utilizzare:
>>> map(lambda d: d.get('value', 'default value'), l)
Aggiornamento: anche io non sono un grande fan di lambdas, preferisco dare un nome alle cose ... ecco come lo farei con questo in mente:
>>> import operator
>>> map(operator.itemgetter('value'), l)
Vorrei anche andare oltre e creare un'unica funzione che dice esplicitamente ciò che voglio ottenere:
>>> import operator, functools
>>> get_values = functools.partial(map, operator.itemgetter('value'))
>>> get_values(l)
... [<list of values>]
Con Python 3, poiché map
restituisce un iteratore, utilizzare list
per restituire un elenco, ad es list(map(operator.itemgetter('value'), l))
.
map
, usa operator.itemgetter('value')
, non a lambda
.
[x['value'] for x in list_of_dicts]
getkey
.. vuoi dire d.get('value')
? Sarebbe lo stesso della seconda lista di comprensione di @ isbadawi, non di Michal.
Per un caso molto semplice come questo, una comprensione, come nella risposta di Ismail Badawi, è sicuramente la strada da percorrere.
Ma quando le cose diventano più complicate e devi iniziare a scrivere comprensioni multi-clausola o nidificate con espressioni complesse in esse, vale la pena cercare altre alternative. Esistono diversi modi (quasi) standard per specificare ricerche in stile XPath su strutture nict dict-and-list, come JSONPath, DPath e KVC. E ci sono belle librerie su PyPI per loro.
Ecco un esempio con la libreria denominata dpath
, che mostra come può semplificare qualcosa di un po 'più complicato:
>>> 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'}]}
Oppure, 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 prima vista, questo potrebbe non sembrare altrettanto semplice, perché find
restituisce oggetti di corrispondenza, che includono tutti i tipi di cose oltre al solo valore corrispondente, come un percorso direttamente a ciascun elemento. Ma per espressioni più complesse, essere in grado di specificare un percorso come al '*.[*].value'
posto di una clausola di comprensione per ciascuno *
può fare una grande differenza. Inoltre, JSONPath è una specifica indipendente dalla lingua e ci sono anche tester online che possono essere molto utili per il debug.
Penso che semplice come sotto ti darebbe quello che stai cercando.
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']
Puoi farlo con una combinazione di map
e lambda
pure, ma la comprensione dell'elenco sembra più elegante e pitonica.
Per una lista di input più piccola la comprensione è la strada da percorrere, ma se l'input è davvero grande, immagino che i generatori siano il modo ideale.
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'
Ecco un confronto di tutte le possibili soluzioni per input più grandi
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)
Come puoi vedere, i generatori sono una soluzione migliore rispetto agli altri, la mappa è anche più lenta rispetto al generatore per la ragione che lascerò all'OP per capire.
Segui l'esempio --
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))))
Ottieni valori chiave dall'elenco dei dizionari in Python?
Ex:
data =
[{'obj1':[{'cpu_percentage':'15%','ram':3,'memory_percentage':'66%'}]},
{'obj2': [{'cpu_percentage':'0','ram':4,'memory_percentage':'35%'}]}]
per d nei dati:
for key,value in d.items():
z ={key: {'cpu_percentage': d['cpu_percentage'],'memory_percentage': d['memory_percentage']} for d in value}
print(z)
Produzione:
{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}