我正在寻找一种正确的方法来扁平化这样的东西
a = [{'name': 'Katie'}, {'name': 'Katie'}, {'name': 'jerry'}]
拥有
d = {}
使用这样的双映射:
map(lambda x: d.update({x:d[x]+1}) if x in d else d.update({x:1}),map(lambda x: x["name"] ,a))
我得到了我想要的结果:
>>> d
{'jerry': 1, 'Katie': 2}
但我觉得可以做得更好。不是列表理解,我觉得这就是我们的地图减少。
我不太喜欢你的解决方案,因为它很难阅读并且有副作用。
对于您提供的示例数据,使用 Counter
(它是内置字典的子类)是更好的方法。
>>> Counter(d['name'] for d in a)
Counter({'Katie': 2, 'jerry': 1})
您可以使用计数器并保持其功能:
In [46]: from collections import Counter
In [47]: from operator import itemgetter
In [48]: Counter(map(itemgetter("name") ,a))
Out[48]: Counter({'Katie': 2, 'jerry': 1})
对于python 2,您将使用itertools.imap
:
Counter(itertools.imap(itemgetter("name") ,a))
在这种情况下
,reduce()
会比map()
更合适:
>>> def count_names(d, x):
... d[x['name']] = d.get(x['name'], 0) + 1
... return d
...
>>> reduce(count_names, a, {})
{'jerry': 1, 'Katie': 2}
from collections import defaultdict
val = defaultdict(int)
for names in a:
val[names['name']] += 1
再次使用计数器,但提取字典。
>>> dict(Counter([i['name'] for i in a]))
{'Katie': 2, 'jerry': 1}
下面是使用分组的更复杂的方法:
from itertools import groupby
>>> dict((name, len(list(totals))) for name, totals in groupby([i["name"] for i in a]))
{'Katie': 2, 'jerry': 1}
for loop 是你的朋友:)
a = [{'name': 'Katie'}, {'name': 'Katie'}, {'name': 'jerry'}]
result = {}
for data in a:
if data['name'] not in result:
result[data['name']] = 0
result[data['name']] += 1
print result