Mendapatkan daftar nilai dari daftar dicts

185

Saya punya daftar dicts seperti ini:

[{'value': 'apple', 'blah': 2}, 
 {'value': 'banana', 'blah': 3} , 
 {'value': 'cars', 'blah': 4}]

saya ingin ['apple', 'banana', 'cars']

Apa cara terbaik untuk melakukan ini?

SuperString
sumber

Jawaban:

325

Anggap setiap dikt memiliki valuekunci, Anda dapat menulis (dengan asumsi daftar Anda dinamai l)

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

Jika valuemungkin hilang, Anda bisa menggunakan

[d['value'] for d in l if 'value' in d]
Ismail Badawi
sumber
8
Untuk memperlakukan nilai kunci yang hilang, orang juga dapat menggunakan d.get ("key_to_lookup", "alternate_value"). Kemudian, akan terlihat seperti: [d.get ('value', 'alt') untuk d in l]. Jika nilai tidak hadir sebagai kunci, itu hanya akan mengembalikan 'alt'.
abhinav
Terima kasih atas solusinya
Ajay Kumar
"Sihir" ini dikenal sebagai daftar pemahaman docs.python.org/3/tutorial/…
William Ardila
Penolong! Saya telah mencoba / mencari ini untuk objek sqlalchemy sejak lama. Sekarang berhasil seperti [d.value for d in l]terima kasih :)
krupesh Anadkat
34

Berikut cara lain untuk melakukannya menggunakan fungsi map () dan lambda:

>>> map(lambda d: d['value'], l)

dimana l adalah daftarnya. Saya melihat ini "paling seksi", tetapi saya akan melakukannya dengan menggunakan daftar pemahaman.

Pembaruan: Seandainya 'nilai' mungkin hilang sebagai penggunaan utama:

>>> map(lambda d: d.get('value', 'default value'), l)

Update: Saya juga bukan penggemar lambdas, saya lebih suka menyebutkan beberapa hal ... ini adalah bagaimana saya akan melakukannya dengan itu dalam pikiran:

>>> import operator
>>> map(operator.itemgetter('value'), l)

Saya bahkan akan melangkah lebih jauh dan membuat satu-satunya fungsi yang secara eksplisit mengatakan apa yang ingin saya capai:

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

Dengan Python 3, sejak mapmengembalikan sebuah iterator, gunakan listuntuk mengembalikan daftar, misalnya list(map(operator.itemgetter('value'), l)).

Anler
sumber
1
Kotor! Pemahaman daftar jauh lebih masuk akal di sini.
Mike Graham
4
Jika Anda akan menggunakan yang pertama map, gunakan operator.itemgetter('value'), bukan a lambda.
agf
18
[x['value'] for x in list_of_dicts]
Michał Trybus
sumber
atau [d.getkey ('value') untuk d di dict_list]
rplnt
1
@ rpInt Um, tidak ada yang namanya getkey.. maksud Anda d.get('value')? Itu akan sama dengan pemahaman daftar ke-2 @ isbadawi, bukan pemahaman Michal.
agf
3
Ya, maaf, maksudku dapatkan. Dan saya maksudkan sebagai sesuatu yang tidak akan membuang pengecualian jika kunci tidak ada. Tetapi solusi @ isbadawi lebih baik karena get () akan menyediakan Tidak Ada (atau apa pun yang kami tentukan sebagai default) ketika kunci hilang.
rplnt
5

Untuk kasus yang sangat sederhana seperti ini, pemahaman, seperti dalam jawaban Ismail Badawi jelas merupakan jalan yang harus ditempuh.

Tetapi ketika segala sesuatunya menjadi lebih rumit, dan Anda perlu mulai menulis multi-klausa atau pemahaman bersarang dengan ekspresi kompleks di dalamnya, ada baiknya mencari alternatif lain. Ada beberapa cara standar (kuasi) untuk menentukan pencarian gaya XPath pada struktur dict-and-list bersarang, seperti JSONPath, DPath, dan KVC. Dan ada perpustakaan bagus di PyPI untuk mereka.

Berikut ini contoh dengan nama perpustakaan dpath, yang menunjukkan bagaimana perpustakaan dapat menyederhanakan sesuatu yang sedikit lebih rumit:

>>> 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'}]}

Atau, menggunakan 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']

Yang satu ini mungkin tidak terlihat sesederhana pada pandangan pertama, karena findmengembalikan objek yang cocok, yang mencakup semua jenis hal selain hanya nilai yang cocok, seperti jalur langsung ke setiap item. Tetapi untuk ekspresi yang lebih kompleks, bisa menentukan jalan seperti '*.[*].value'bukannya klausa pemahaman untuk masing-masing *dapat membuat perbedaan besar. Plus, JSONPath adalah spesifikasi bahasa-agnostik, dan bahkan ada penguji online yang bisa sangat berguna untuk debugging.

abarnert
sumber
1

Saya pikir sesederhana di bawah ini akan memberi Anda apa yang Anda cari.

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']

Anda dapat melakukan ini dengan kombinasi mapdanlambda juga tetapi daftar pemahaman terlihat lebih elegan dan pythonic.

Untuk pemahaman daftar input yang lebih kecil adalah cara untuk pergi tetapi jika input benar-benar besar maka saya kira generator adalah cara yang 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'

Berikut ini adalah perbandingan dari semua solusi yang mungkin untuk input yang lebih besar

 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)

Seperti yang Anda lihat, generator adalah solusi yang lebih baik dibandingkan dengan yang lain, peta juga lebih lambat dibandingkan dengan generator karena alasan saya akan menyerahkan OP untuk mencari tahu.

Rohit
sumber
1

Ikuti contohnya --

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))))
Mohan. SEBUAH
sumber
1

Dapatkan nilai kunci dari daftar kamus dengan python?

  1. Dapatkan nilai kunci dari daftar kamus dengan python?

Ex:

data = 
[{'obj1':[{'cpu_percentage':'15%','ram':3,'memory_percentage':'66%'}]},
{'obj2': [{'cpu_percentage':'0','ram':4,'memory_percentage':'35%'}]}]

untuk d dalam data:

  for key,value in d.items(): 

      z ={key: {'cpu_percentage': d['cpu_percentage'],'memory_percentage': d['memory_percentage']} for d in value} 
      print(z)

Keluaran:

{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}
Kalyani B
sumber
-2

Cara yang sangat sederhana untuk melakukannya adalah:

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

Keluaran:

['apel', 'pisang', 'mobil']

Ayushi
sumber