使用reduce方法将具有相似/重复键的字典列表转换为单个字典(值将是列表)



这个问题类似于帖子"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, {})

最新更新