การรับรายการค่าจากรายการ dicts


184

ฉันมีรายการ dicts ดังนี้:

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

ฉันต้องการ ['apple', 'banana', 'cars']

วิธีที่ดีที่สุดในการทำเช่นนี้คืออะไร?

คำตอบ:


324

สมมติว่าทุก dict มี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 in l] ถ้าไม่มีค่าเป็นกุญแจมันก็จะกลับมา 'alt'
abhinav

ขอบคุณสำหรับการแก้ปัญหา
Ajay Kumar

"magic" นี้เรียกว่า list comprehension docs.python.org/3/tutorial/…
William Ardila

34

นี่เป็นอีกวิธีในการใช้ฟังก์ชั่น map () และ lambda:

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

โดยที่ l คือรายการ ฉันเห็นวิธีนี้ "เซ็กซี่ที่สุด" แต่ฉันจะทำโดยใช้รายการความเข้าใจ

อัปเดต: ในกรณีที่ 'ค่า' อาจหายไปเนื่องจากการใช้คีย์:

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

Update: ฉันไม่ใช่แฟนตัวยงของ lambdas ด้วยฉันชอบที่จะตั้งชื่อสิ่งต่าง ๆ ... นี่คือสิ่งที่ฉันจะทำโดยคำนึงถึงสิ่งนั้น:

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

ฉันจะไปต่อและสร้างฟังก์ชั่น แต่เพียงผู้เดียวที่ระบุอย่างชัดเจนว่าสิ่งที่ฉันต้องการบรรลุ:

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

กับงูหลาม 3 ตั้งแต่mapส่งกลับ iterator ใช้เพื่อกลับรายการเช่นlistlist(map(operator.itemgetter('value'), l))


1
Gross! ความเข้าใจในรายการทำให้เข้าใจได้ง่ายขึ้น
Mike Graham

4
หากคุณกำลังจะใช้ครั้งแรกที่mapใช้ไม่ได้operator.itemgetter('value') lambda
agf

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

หรือ [d.getkey ('value') สำหรับ d ใน dict_list]
rplnt

1
@rpInt อืมไม่มีเรื่องแบบนี้getkey.. คุณหมายถึงd.get('value')อะไร? นั่นจะเป็นเช่นเดียวกับความเข้าใจในรายการที่ 2 ของ @ isbadawi ไม่ใช่ของมิคาล
agf

3
ใช่ขอโทษฉันหมายถึงรับ และฉันหมายถึงมันเป็นสิ่งที่จะไม่เกิดข้อยกเว้นหากคีย์หายไป แต่วิธีการแก้ปัญหาของ @ isbadawi นั้นดีกว่าเพราะ get () จะให้ None (หรืออะไรก็ตามที่เราระบุเป็นค่าเริ่มต้น) เมื่อคีย์หายไป
rplnt

5

สำหรับกรณีที่ง่ายมากเช่นนี้ความเข้าใจเช่นเดียวกับคำตอบของ Ismail Badawiเป็นวิธีการที่แน่นอน

แต่เมื่อสิ่งต่าง ๆ มีความซับซ้อนมากขึ้นและคุณต้องเริ่มเขียนความเข้าใจในหลายประโยคหรือซ้อนกันด้วยการแสดงออกที่ซับซ้อนในสิ่งเหล่านั้นมันคุ้มค่าที่จะมองหาทางเลือกอื่น มีวิธีมาตรฐาน (quasi-) ที่แตกต่างกันเล็กน้อยในการระบุการค้นหาสไตล์ 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)

อย่างที่คุณเห็นเครื่องปั่นไฟเป็นทางออกที่ดีกว่าเมื่อเทียบกับเครื่องอื่น ๆ แผนที่ก็ช้าลงเมื่อเทียบกับเครื่องกำเนิดไฟฟ้าด้วยเหตุผลที่ฉันจะออกจาก OP เพื่อคิดออก


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

รับค่าคีย์จากรายการพจนานุกรมในหลามหรือไม่

  1. รับค่าคีย์จากรายการพจนานุกรมในหลามหรือไม่

Ex:

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

เอาท์พุท:

['apple', 'Banana', 'cars']

โดยการใช้ไซต์ของเรา หมายความว่าคุณได้อ่านและทำความเข้าใจนโยบายคุกกี้และนโยบายความเป็นส่วนตัวของเราแล้ว
Licensed under cc by-sa 3.0 with attribution required.