Lấy danh sách các giá trị từ danh sách các giá trị


184

Tôi có một danh sách các dicts như thế này:

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

tôi muốn ['apple', 'banana', 'cars']

Cách tốt nhất để làm điều này là gì?

Câu trả lời:


324

Giả sử mỗi dict có một valuekhóa, bạn có thể viết (giả sử danh sách của bạn được đặt tên l)

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

Nếu valuecó thể bị thiếu, bạn có thể sử dụng

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

8
Để xử lý giá trị bị thiếu cho một khóa, người ta cũng có thể sử dụng d.get ("key_to_lookup", "Alternate_value"). Sau đó, nó sẽ trông giống như: [d.get ('value', 'alt') cho d trong l]. Nếu giá trị không xuất hiện dưới dạng khóa, nó sẽ chỉ trả về 'alt'.
abhinav

Cảm ơn giải pháp
Ajay Kumar

"Phép thuật" này được gọi là tài liệu hiểu danh sách docs.python.org/3/tutorial/ Khăn
William Ardila

34

Đây là một cách khác để làm điều đó bằng cách sử dụng các hàm map () và lambda:

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

Trong đó l là danh sách. Tôi thấy cách này "quyến rũ nhất", nhưng tôi sẽ làm nó bằng cách hiểu danh sách.

Cập nhật: Trong trường hợp 'giá trị' có thể bị thiếu khi sử dụng khóa:

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

Cập nhật: Tôi cũng không phải là một fan hâm mộ lớn của lambdas, tôi thích đặt tên cho mọi thứ ... đây là cách tôi sẽ làm điều đó với ý nghĩ đó:

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

Tôi thậm chí sẽ đi xa hơn và tạo ra một chức năng duy nhất nói rõ ràng những gì tôi muốn đạt được:

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

Với Python 3, vì maptrả về một iterator, hãy sử dụng listđể trả về một danh sách, vd list(map(operator.itemgetter('value'), l)).


1
Tổng! Việc hiểu danh sách làm cho nhiều ý nghĩa hơn ở đây.
Mike Graham

4
Nếu bạn sẽ sử dụng đầu tiên map, sử dụng operator.itemgetter('value'), không phải a lambda.
agf

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

hoặc [d.getkey ('value') cho d trong dict_list]
rplnt

1
@rpInt Um, không có getkeyý nghĩa d.get('value')gì cả .. ý bạn là sao? Điều đó sẽ giống như sự hiểu biết danh sách thứ 2 của @ isbadawi, không phải của Michal.
agf

3
Vâng, xin lỗi, tôi có nghĩa là có được. Và tôi có nghĩa nó là thứ gì đó sẽ không ném ngoại lệ nếu thiếu khóa. Nhưng giải pháp của @ isbadawi là tốt hơn vì get () sẽ cung cấp Không (hoặc bất cứ điều gì chúng tôi chỉ định làm mặc định) khi thiếu khóa.
rplnt

5

Đối với một trường hợp rất đơn giản như thế này, một sự hiểu biết, như trong câu trả lời của Ismail Badawi chắc chắn là con đường để đi.

Nhưng khi mọi thứ trở nên phức tạp hơn, và bạn cần bắt đầu viết các mệnh đề đa mệnh đề hoặc lồng nhau với các biểu thức phức tạp trong đó, thì đáng để xem xét các lựa chọn thay thế khác. Có một số cách khác nhau (gần đúng) để chỉ định các tìm kiếm kiểu XPath trên các cấu trúc chính tả và danh sách lồng nhau, chẳng hạn như JSONPath, DPath và KVC. Và có những thư viện đẹp trên PyPI cho họ.

Đây là một ví dụ với thư viện có tên dpath, cho thấy cách nó có thể đơn giản hóa một cái gì đó phức tạp hơn một chút:

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

Hoặc, sử dụng 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']

Cái này thoạt nhìn có thể trông không đơn giản, bởi vì findtrả về các đối tượng khớp, bao gồm tất cả các loại ngoài giá trị khớp, chẳng hạn như đường dẫn trực tiếp đến từng mục. Nhưng đối với các biểu thức phức tạp hơn, việc có thể chỉ định một đường dẫn như '*.[*].value'thay vì mệnh đề hiểu cho từng mệnh đề *có thể tạo ra sự khác biệt lớn. Thêm vào đó, JSONPath là một đặc tả không biết ngôn ngữ và thậm chí có những người kiểm tra trực tuyến có thể rất thuận tiện để gỡ lỗi.


1

Tôi nghĩ đơn giản như dưới đây sẽ cung cấp cho bạn những gì bạn đang tìm kiếm.

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

Bạn có thể làm điều này với sự kết hợp maplambdacũng như nhưng việc hiểu danh sách trông thanh lịch và pythonic hơn.

Đối với một sự hiểu biết danh sách đầu vào nhỏ hơn là cách để đi nhưng nếu đầu vào thực sự lớn thì tôi đoán máy phát điện là cách lý tưởng.

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'

Dưới đây là so sánh tất cả các giải pháp có thể cho đầu vào lớn hơn

 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)

Như bạn có thể thấy, máy phát điện là một giải pháp tốt hơn so với các máy khác, bản đồ cũng chậm hơn so với máy phát điện vì lý do tôi sẽ rời khỏi OP để tìm ra.


1

Thực hiện theo ví dụ -

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

Lấy giá trị chính từ danh sách từ điển trong python?

  1. Lấy giá trị chính từ danh sách từ điển trong python?

Ví dụ:

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

cho d trong dữ liệu:

  for key,value in d.items(): 

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

Đầu ra:

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

-2

Một cách rất đơn giản để làm điều đó là:

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

Đầu ra:

['Táo', 'chuối', 'ô tô']

Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.