3

私はこのような辞書を持っています。

data={11L: [{'a': 2, 'b': 1},{'a': 2, 'b': 3}],
22L: [{'a': 3, 'b': 2},{'a': 2, 'b': 5},{'a': 4, 'b': 2},{'a': 1, 'b': 5}, {'a': 1, 'b': 0}],
33L: [{'a': 1, 'b': 2},{'a': 3, 'b': 5},{'a': 5, 'b': 2},{'a': 1, 'b': 3}, {'a': 1, 'b': 6},{'a':2,'b':0}],
44L: [{'a': 4, 'b': 2},{'a': 4, 'b': 5},{'a': 3, 'b': 1},{'a': 3, 'b': 3}, {'a': 2, 'b': 3},{'a':1,'b':2},{'a': 1, 'b': 0}]}

ここでは、外側のキーを取り除き、新しいキー値 1、2、3 などを与えます。以下に示すような結果を取得したいと思います。

result={1:{'a':10,'b':7},2:{'a':11,'b':18},3:{'a':12,'b':5},4:{'a':5,'b':11},5:{'a':3,'b':9},6:{'a':3,'b':2},7:{'a':1,'b':0}}

このようなことを試しましたが、必要な結果が得られませんでした。

d = defaultdict(int)
for dct in data.values():
  for k,v in dct.items():
    d[k] += v
print dict(d)

上記のデータ ディクショナリのように、結果ディクショナリのキーを動的にしたいのですが、7 つのキーと値のペアで最大の 44 があるため、結果ディクショナリには 7 つのキーなどがあります。

4

3 に答える 3

5

ここでリストを使用したいのですが、おそらくCounter()オブジェクトを使用して、合計をより簡単にしたいと考えています。

from collections import Counter
from itertools import izip_longest

for dcts in data.values():
    for i, dct in enumerate(dcts):
        if i >= len(result):
            result.append(Counter(dct))
        else:
            result[i].update(dct)

結果:

>>> result
[Counter({'a': 10, 'b': 7}), Counter({'b': 18, 'a': 11}), Counter({'a': 12, 'b': 5}), Counter({'b': 11, 'a': 5}), Counter({'b': 9, 'a': 4}), Counter({'a': 3, 'b': 2}), Counter({'a': 1, 'b': 0})]

Counter()オブジェクトは のサブクラスでdictあるため、それ以外の場合は辞書として動作します。後で値が必要な場合dict、次の行を追加します。

result = [dict(r) for r in result]

Eric からインスピレーションを得て、上記をワンライナーに変換できます。

from collections import Counter
from itertools import izip_longest

result = [sum(map(Counter, col), Counter()) 
    for col in izip_longest(*data.values(), fillvalue={})]

このバージョンは、合計時に 0 のキーがカウンターから削除されるという点で、上記のループとは少し異なります。'b': 0最後のカウンターを保持したい場合は、次を使用します。

[reduce(lambda c, d: c.update(d) or c, col, Counter())
    for col in izip_longest(*data.values(), fillvalue={})]

これはまた使い.update()ます。

于 2013-05-20T08:12:58.377 に答える
2

izip_longest行を転置できます。

from itertools import izip_longest

print [
    {
       'a': sum(cell['a'] for cell in column), 
       'b': sum(cell['b'] for cell in column)
    }
    for column in izip_longest(*data.values(), fillvalue={'a': 0, 'b': 0})
]
[{'a': 10, 'b': 7}, {'a': 11, 'b': 18}, {'a': 12, 'b': 5}, {'a': 5, 'b': 11}, {'a': 4, 'b': 9}, {'a': 3, 'b': 2}, {'a': 1, 'b': 0}]

またはそれをカウンターと組み合わせる:

print [
    sum(Counter(cell) for cell in column, Counter())
    for column in izip_longest(*data.values(), fillvalue={})
]
[Counter({'a': 10, 'b': 7}), Counter({'b': 18, 'a': 11}), Counter({'a': 12, 'b': 5}), Counter({'b': 11, 'a': 5}), Counter({'b': 9, 'a': 4}), Counter({'a': 3, 'b': 2}), Counter({'a': 1, 'b': 0})]
于 2013-05-20T08:12:23.163 に答える