Отримання списку значень зі списку диктів


184

У мене є список таких диктів:

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

я хочу ['apple', 'banana', 'cars']

Який найкращий спосіб зробити це?

Відповіді:


324

Якщо припустимо, що кожен дикт має valueключ, ви можете написати (якщо ваш список названий l)

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

Якщо valueможе бути відсутнім, ви можете використовувати

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

8
Для обробки відсутнього значення ключа можна також використовувати d.get ("key_to_lookup", "alternate_value"). Тоді це буде виглядати так: [d.get ('value', 'alt') для d в l]. Якщо значення не є ключовим, воно просто поверне «alt».
abhinav

Дякую за рішення
Аджай Кумар

Ця "магія" відома як осмислення списку docs.python.org/3/tutorial/…
Вільям Арділа

34

Ось ще один спосіб зробити це за допомогою функції map () та лямбда:

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

де l - список. Я вважаю цей спосіб "найсексуальнішим", але я би це зробив, використовуючи розуміння списку.

Оновлення: У разі, якщо значення "може" відсутнє як ключове використання:

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

Оновлення: Я також не є великим шанувальником лямбдів, я вважаю за краще називати речі ... ось як я це зробив, маючи це на увазі:

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

Я б навіть пішов далі і створив єдину функцію, яка прямо говорить про те, чого я хочу досягти:

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

З Python 3, оскільки mapповертає ітератор, використовуйте listдля повернення списку, наприклад list(map(operator.itemgetter('value'), l)).


1
Валовий! Розуміння списку має тут набагато більше сенсу.
Майк Грехем

4
Якщо ви збираєтесь використовувати перший map, використовуйте operator.itemgetter('value'), а не a lambda.
agf

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

або [d.getkey ('значення') для d у dict_list]
rplnt

1
@rpInt Гм, немає такого поняття, як getkey... ти маєш на увазі d.get('value')? Це було б так само, як розуміння другого списку @ isbadawi, а не Міхал.
agf

3
Так, вибачте, я мав на увазі отримати. І я мав на увазі це як щось, що не кине виключення, якщо ключ відсутній. Але рішення @ isbadawi краще, оскільки get () надасть None (або все, що ми вказамо як за замовчуванням), коли ключ відсутній.
rplnt

5

Для дуже простого випадку, як це, розуміння, як у відповіді Ісмаїла Бадаві, безумовно, це шлях.

Але коли справи ускладнюються, і вам потрібно почати писати багатозначні або вкладені розуміння зі складними виразами в них, варто розглянути інші варіанти. Існує кілька різних (квазі-) стандартних способів задати пошук у стилі XPath для вкладених структур dict-and-list, таких як JSONPath, DPath та KVC. І є приємні бібліотеки на PyPI для них.

Ось приклад з назвою бібліотеки dpath, який показує, як можна спростити щось трохи складніше:

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

Або, використовуючи 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']

Цей на перший погляд може виглядати не так просто, тому що findповертає об'єкти відповідності, які включають всі види речей, окрім лише відповідного значення, наприклад шлях безпосередньо до кожного елемента. Але для більш складних виразів можливість встановлення шляху, як '*.[*].value'замість пункту розуміння для кожного, *може призвести до великої зміни. Крім того, JSONPath - це мовно-агностична специфікація, і є навіть онлайн-тестери, які можуть бути дуже зручними для налагодження.


1

Я думаю, що так просто, як нижче, дасть вам те, що ви шукаєте.

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

Ви можете зробити це за допомогою комбінації mapта lambda, але розуміння списку виглядає більш елегантно та пітонічно.

Для меншого списку вхідних даних розуміння - це шлях, але якщо введення дійсно велике, то, я думаю, генератори - ідеальний шлях.

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'

Ось порівняння всіх можливих рішень для більшого введення

 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)

Як бачите, генератори є кращим рішенням порівняно з іншими, карта також повільніше порівняно з генератором, тому я залишу до ОП розібратися.


1

Дотримуйтесь прикладу -

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

1

Отримати ключові значення зі списку словників у python?

  1. Отримати ключові значення зі списку словників у python?

Наприклад:

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

для d у даних:

  for key,value in d.items(): 

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

Вихід:

{'obj1': {'cpu_percentage': '15%', 'memory_percentage': '66%'}}
{'obj2': {'cpu_percentage': '0', 'memory_percentage': '35%'}}

-2

Дуже простий спосіб зробити це:

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

Вихід:

["яблуко", "банан", "машини"]

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.