简体   繁体   English

在词典列表中使用reduce

[英]Using reduce on a list of dictionaries of dictionaries

Here is the given list. 这是给定的列表。

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

I need to use the map and reduce function so that I can have a final result of 我需要使用map和reduce函数,以便我可以得到最终结果

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

I have written a function using map 我用地图写了一个函数

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)

That returns 那回来了

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

It combines the f1 and f2 of the first and second dictionaries, but I am unsure of how to use reduce on the dictionaries to get the final result. 它结合了第一和第二个词典的f1和f2,但我不确定如何在词典中使用reduce来获得最终结果。

You can use collections.Counter to sum your list of counter dictionaries. 您可以使用collections.Counter计数器词典列表。

Moreover, your dictionary flattening logic can be optimised via itertools.chain . 此外,您的字典展平逻辑可以通过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})

This works for an arbitrary length list of dictionaries, with no key matching requirements across dictionaries. 这适用于任意长度的字典列表,字典中没有键匹配要求。

The second parameter of sum is a start value. sum的第二个参数是起始值。 It is set to an empty Counter object to avoid TypeError . 它被设置为一个空的Counter对象以避免TypeError

Without using map and reduce , I would be inclined to do something like this: 不使用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

Using reduce (which really is not the right function for the job, and is not in Python 3) on your current progress would be something like this: 在当前进度中使用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())

You can use purely map and reduce like so: 你可以像这样使用纯粹的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))

Output: 输出:

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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM