我有一个字典列表,像这样:

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

我想要['苹果','香蕉','汽车']

做这件事最好的方法是什么?


当前回答

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

其他回答

假设每个字典都有一个值键,你可以这样写(假设你的列表名为l)

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

如果价值可能丢失,您可以使用

[d['value'] for d in l if 'value' in 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))))
[x['value'] for x in list_of_dicts]

我想简单如下就能给你你想要的。

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的组合来做到这一点,但是列表理解看起来更优雅,更python化。

对于一个较小的输入列表,理解是要走的路,但如果输入真的很大,那么我猜生成器是理想的方式。

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)

正如你所看到的,生成器是一个比其他更好的解决方案,map也比生成器慢,原因我将留给OP来解决。

下面是使用map()和lambda函数的另一种方法:

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

其中l是列表。 我这样看“最性感”,但我会用列表理解来做。

更新: 以防“value”作为键的使用可能会丢失:

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

更新:我也不是lambdas的大粉丝,我更喜欢命名事物…这就是我的做法:

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

我甚至会进一步创建一个明确表示我想要实现的功能:

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

在Python 3中,由于map返回一个迭代器,所以使用list返回一个列表,例如list(map(operator.itemgetter('value'), l))。