在词典列表中使用reduce

时间:2018-03-11 01:58:14

标签: python list dictionary reduce

这是给定的清单。

   Pets = [{'f1': {'dogs': 2, 'cats': 3, 'fish': 1},
         'f2': {'dogs': 3, 'cats': 2}},
        {'f1': {'dogs': 5, 'cats': 2, 'fish': 3}}]

我需要使用map和reduce函数,以便我可以得到

的最终结果
{'dogs': 10, 'cats': 7, 'fish': 4}

我用地图

编写了一个函数
def addDict(d):
    d2 = {}
    for outKey, inKey in d.items():
        for inVal in inKey:
            if inVal in d2:
                d2[inVal] += inKey[inVal]
            else:
                d2[inVal] = inKey[inVal]
    return d2


def addDictN(L):
    d2 = list(map(addDict, L))
    print(d2)

返回

[{'dogs': 5, 'cats': 5, 'fish': 1}, {'dogs': 5, 'cats': 2, 'fish': 3}]

它结合了第一个和第二个词典的f1和f2,但我不确定如何在词典上使用reduce来获得最终结果。

3 个答案:

答案 0 :(得分:2)

您可以使用collections.Counter对计数词典列表求和。

此外,您的字典展平逻辑可以通过itertools.chain进行优化。

from itertools import chain
from collections import Counter

Pets = [{'f1': {'dogs': 2, 'cats': 3, 'fish': 1},
         'f2': {'dogs': 3, 'cats': 2}},
        {'f1': {'dogs': 5, 'cats': 2, 'fish': 3}}]

lst = list(chain.from_iterable([i.values() for i in Pets]))

lst_sum = sum(map(Counter, lst), Counter())

# Counter({'cats': 7, 'dogs': 10, 'fish': 4})

这适用于任意长度的词典列表,而词典中没有键匹配要求。

sum的第二个参数是起始值。它被设置为一个空的Counter对象以避免TypeError

答案 1 :(得分:1)

不使用mapreduce,我倾向于做这样的事情:

from collections import defaultdict
result = defaultdict()
for fdict in pets:
    for f in fdict.keys():
        for pet, count in fdict[f].items():
            result[pet] += count

在当前的进度中使用reduce(对于作业来说,不是正确的函数,而不是在Python 3中)将是这样的:

from collections import Counter
pets = [{'dogs': 5, 'cats': 5, 'fish': 1}, {'dogs': 5, 'cats': 2, 'fish': 3}]
result = reduce(lambda x, y: x + Counter(y), pets, Counter())

答案 2 :(得分:0)

您可以像以下一样纯粹使用mapreduce

Pets = [{'f1': {'dogs': 2, 'cats': 3, 'fish': 1},
     'f2': {'dogs': 3, 'cats': 2}},
    {'f1': {'dogs': 5, 'cats': 2, 'fish': 3}}]

new_pets = reduce(lambda x, y:[b.items() for _, b in x.items()]+[b.items() for _, b in y.items()], Pets)
final_pets = dict(reduce(lambda x, y:map(lambda c:(c, dict(x).get(c, 0)+dict(y).get(c, 0)), ['dogs', 'cats', 'fish']), new_pets))

输出:

{'fish': 4, 'cats': 7, 'dogs': 10}