python字典有两个运行总计

时间:2013-09-07 08:22:41

标签: python dictionary

我的数据由一系列类别组成,每个类别都有两个数量。例如,{'cat':'red', 'a':1, 'b':2}, {'cat':'red', 'a':3, 'b':3}, {'cat':'blue', 'a':1, 'b':3}

我希望按类别保持两个金额的总计。结果将是{'cat':'red', 'a':4, 'b':5}, {'cat':'blue', 'a':1, 'b':3}

是否有更多的pythonic方法:

totals = {}
for item in data:
    if item['cat'] in totals:
        totals[item['cat']]['a'] += item['a']
        totals[item['cat']]['b'] += item['b']
    else:
        totals[item['cat']] = {'a':item['a'], 'b':item['b']}

3 个答案:

答案 0 :(得分:2)

您的数据结构应该真正移动到字典,键入cat值。使用collections.defaultdict()collections.Counter()来跟踪这些值并简化求和:

from collections import defaultdict, Counter

totals = defaultdict(Counter)

for item in data:
    cat = item.pop('cat')
    totals[cat] += Counter(item)

演示:

>>> from collections import defaultdict, Counter
>>> data = {'cat':'red', 'a':1, 'b':2}, {'cat':'red', 'a':3, 'b':3}, {'cat':'blue', 'a':1, 'b':3}
>>> totals = defaultdict(Counter)
>>> for item in data:
...     cat = item.pop('cat')
...     totals[cat] += Counter(item)
... 
>>> totals
defaultdict(<class 'collections.Counter'>, {'blue': Counter({'b': 3, 'a': 1}), 'red': Counter({'b': 5, 'a': 4})})
>>> totals['blue']
Counter({'b': 3, 'a': 1})
>>> totals['red']
Counter({'b': 5, 'a': 4})

如果您仍需要相同格式的字典序列,则可以将上述字典字典再次转换为“普通”字典:

output = []
for cat, counts in totals.iteritems():
    item = {'cat': cat}
    item.update(counts)
    output.append(item)

导致:

>>> output
[{'a': 1, 'b': 3, 'cat': 'blue'}, {'a': 4, 'b': 5, 'cat': 'red'}]

答案 1 :(得分:1)

查看dict.setdefaultcollections.counter。 使用setdefault的可能解决方案:

totals = {}
for item in data:
    d = totals.setdefault(item['cat'],  {'a':0, 'b':0})
    d['a'] += item['a']
    d['b'] += item['b']

结果为total = {'blue': {'a': 1, 'b': 3}, 'red': {'a': 4, 'b': 5}}。请注意,这没有预期答案中的'cat'条目。相反,颜色直接用作结果字典的键。

请参阅Martijn的答案,了解使用Counter的示例。

答案 2 :(得分:0)

我会根据collections.Countercollections.defaultdict类的组合将您的数据收集到临时复合数据结构中。这个数据结构的关键是猫的颜色,并且与每个颜色相关联将是Counter来保存每个颜色猫的总数。将它设为defaultdict意味着不必担心它是否第一次遇到颜色。

这将在创建时执行所需值的求和,并且很容易变成您想要的输出序列:

from collections import Counter, defaultdict

data = ({'cat':'red', 'a':1, 'b':2},
        {'cat':'red', 'a':3, 'b':3},
        {'cat':'blue', 'a':1, 'b':3})

cat_totals = defaultdict(Counter)  # hybrid data structure
for entry in data:
    cat_totals[entry['cat']].update({k:v for k,v in entry.iteritems() 
                                            if k != 'cat'})

results = tuple(dict([('cat', color)] + cat_totals[color].items())
            for color in cat_totals)

print results # ({'a': 1, 'b': 3, 'cat': 'blue'}, {'a': 4, 'b': 5, 'cat': 'red'})