这个问题类似于帖子"Python - 将单键词典列表转换为单个词典",其中假设我们保证词典列表中的不同键。我的问题是,如果我们有类似的键以及如何利用reduce函数怎么办。
例如,我们有:
lst = [{'1': 'A'}, {'1': 'B'}, {'2': 'C'}, {'2': 'D'}, {'3': 'E'}]
我们希望成为:
dict = {'1': ['A', 'B'], '2': ['C', 'D'], '3': ['E']}
此外,帖子 如何合并具有相同键的多个字典?是类似的,只是这里我们想使用 reduce 方法。
好的,从链接的问题中汲取灵感,你可以这样做:
In [12]: from collections import defaultdict
...: from functools import reduce
In [13]: lst = [{'1': 'A'}, {'1': 'B'}, {'2': 'C'}, {'2': 'D'}, {'3': 'E'}]
In [14]: def foo(r, d):
...: for k in d:
...: r[k].append(d[k])
...:
In [16]: d = reduce(lambda r, d: foo(r, d) or r, lst, defaultdict(list))
In [17]: d
Out[17]: defaultdict(list, {'1': ['A', 'B'], '2': ['C', 'D'], '3': ['E']})
您需要一个中间函数来执行更新...我认为有更好的方法可以做到这一点,但这是它的关键。
现在,如果你想要一种更干净、更易读的方式,你可以这样做:
In [12]: from collections import defaultdict
In [30]: lst = [{'1': 'A'}, {'1': 'B'}, {'2': 'C'}, {'2': 'D'}, {'3': 'E'}]
In [31]: d = defaultdict(list)
In [32]: for i in lst:
...: k, v = list(i.items())[0] # an alternative to the single-iterating inner loop from the previous solution
...: d[k].append(v)
...:
In [33]: d
Out[33]: defaultdict(list, {'1': ['A', 'B'], '2': ['C', 'D'], '3': ['E']})
您可以使用字典对象的setdefault()
属性:
>>> def combine(dictionaries):
combined_dict = {}
for dictionary in dictionaries:
for key, value in dictionary.items():
combined_dict.setdefault(key, []).append(value)
return combined_dict
>>>
>>> lst = [{'1': 'A'}, {'1': 'B'}, {'2': 'C'}, {'2': 'D'}, {'3': 'E'}]
>>> combine(lst)
{'1': ['A', 'B'], '2': ['C', 'D'], '3': ['E']}
>>>
这基本上是通过首先检查键是否已存在于新字典中来工作的。如果是这样,我们只需将当前值附加到同一键。如果没有,我们创建一个新键并将该当前值附加到该键。
我刚刚想出了一个使用reduce方法的函数的解决方案。
首先,我们定义一个函数来检查键之前是否插入了字典。如果它是一个新键,我们将它添加到字典中,并在列表中显示值,如果它已经存在,我们将值附加到现有列表中。
def dict_list(each_dict):
d_key = each_dict.keys()[0]
d_value = each_dict.values()[0]
if d_key in return_dict:
return_dict[d_key].append(d_value)
else:
return_dict[d_key] = [d_value]
return return_dict
然后在一行中将此功能与reduce一起使用,如下所示:
lst = [{'1': 'A'}, {'1': 'B'}, {'2': 'C'}, {'2': 'D'}, {'3': 'E'}]
return_dict = {}
print reduce(lambda return_dict, each_dict: dict_list(each_dict), lst, {})