Python - 用条件汇总字典列表

时间:2013-04-21 14:48:21

标签: python dictionary sum conditional-statements

假设我有一个清单:

l = [{"num1":3, "num2":8, "num3":5, "type":"A"}, {"num1":2, "num2":5, "num3":5, "type":"B"}, {"num1":5, "num2":2, "num3":1, "type":"A"}, {"num1":4, "num2":4, "num3":9, "type":"B"}

我想创建2个词典: SUMA:

{"num1":8, "num2":10, "num3":6}

sumB:

{"num1":6, "num2":9, "num3":14}

我希望尽可能简单易读。 我设法用太多变量以可怕的方式做到了......

谢谢!

3 个答案:

答案 0 :(得分:1)

使用一些list and dict comprehensions可以很容易地做到这一点。

from operator import itemgetter
from itertools import groupby

l = [{"num1": 3, "num2": 8, "num3": 5, "type": "A"},
     {"num1": 2, "num2": 5, "num3": 5, "type": "B"},
     {"num1": 5, "num2": 2, "num3": 1, "type": "A"},
     {"num1": 4, "num2": 4, "num3": 9, "type": "B"}]

wanted_values = {"num1", "num2", "num3"}

type_getter = itemgetter("type")
groups = [(group, list(items)) for group, items in 
          groupby(sorted(l, key=type_getter), type_getter)]

print({group: {k: sum(map(itemgetter(k), items)) for k in wanted_values}
       for group, items in groups})

这给了我们:

{'B': {'num2': 9, 'num3': 14, 'num1': 6}, 
 'A': {'num2': 10, 'num3': 6, 'num1': 8}}

我们按类型对值进行排序,然后将它们分成itertools.groupby()组(使项目列表而不是生成器,因为我们需要多次迭代它们)。

然后我们使用嵌套的字典理解来创建我们需要的数据,将项目中的值相加并将它们分配给一个组。

这是一个灵活的解决方案,可以扩展到只有两种类型。

答案 1 :(得分:0)

我会使用嵌套理解。

lst = [{"num1": 3, "num2": 8, "num3": 5, "type": "A"},
     {"num1": 2, "num2": 5, "num3": 5, "type": "B"},
     {"num1": 5, "num2": 2, "num3": 1, "type": "A"},
     {"num1": 4, "num2": 4, "num3": 9, "type": "B"}]

sum_by_a = {key: sum(d[key] for d in lst if d['type'] == 'A')
    for key in ("num1", "num2", "num3")}

或者,对于泛型类型,

sum_by_type = lambda t: {
    key: sum(d[key] for d in lst if d['type'] == t)
        for key in ("num1", "num2", "num3")}

 sum_by_b = sum_by_type(B)

答案 2 :(得分:0)

我会这样做,使用Collections.Counter

from collections import Counter
from functools import reduce

l = [{"num1":3, "num2":8, "num3":5, "type":"A"},
     {"num1":2, "num2":5, "num3":5, "type":"B"},
     {"num1":5, "num2":2, "num3":1, "type":"A"},
     {"num1":4, "num2":4, "num3":9, "type":"B"}]

def remove_keys(d, keys):
    return {i: j for i, j in d.items() if i not in keys}

def add_dicts(dicts):
    return reduce(lambda a, b: a+b,  map(Counter, dicts))

tmp = {}
for d in l:
    tmp[d["type"]] = tmp.get(d["type"], []) + [remove_keys(d, ["type"])]

result = {key: add_dicts(value) for key, value in dict(tmp).items()}

给出:

{'A': Counter({'num2': 10, 'num1': 8, 'num3': 6}), 
'B': Counter({'num3': 14, 'num2': 9, 'num1': 6})}