1

假设我有一个清单:

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}

总和B:

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

我想让它尽可能简单易读。我设法以一种可怕的方式使用太多变量来做到这一点......

谢谢!

4

3 回答 3

1

这可以使用一些list 和 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()(制作项目列表而不是生成器,因为我们需要多次迭代它们)。

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

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

于 2013-04-21T14:54:40.877 回答
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)
于 2013-04-21T15:12:14.210 回答
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})}
于 2013-04-21T15:16:16.867 回答