web-dev-qa-db-ja.com

Python:defaultdictのdefaultdict?

次のコードを機能させるためにdefaultdict(defaultdict(int))を使用する方法はありますか?

for x in stuff:
    d[x.a][x.b] += x.c_int

dは、x.aおよびx.b要素に応じて、アドホックに構築する必要があります。

私は使用できます:

for x in stuff:
    d[x.a,x.b] += x.c_int

しかし、私は使用できません:

d.keys()
d[x.a].keys()
273
Jonathan

はい、このように:

defaultdict(lambda: defaultdict(int))

存在しないキーにアクセスしようとすると、defaultdict(この場合はlambda: defaultdict(int))の引数が呼び出されます。戻り値はこのキーの新しい値として設定されます。つまり、この場合、d[Key_doesnt_exist]の値はdefaultdict(int)になります。

この最後のdefaultdictからキーにアクセスしようとすると、つまりd[Key_doesnt_exist][Key_doesnt_exist]は、0を返します。これは、最後のdefaultdictの引数の戻り値、つまりint()です。

499
mouad

Defaultdictコンストラクターのパラメーターは、新しい要素を構築するために呼び出される関数です。ラムダを使用しましょう!

>>> from collections import defaultdict
>>> d = defaultdict(lambda : defaultdict(int))
>>> print d[0]
defaultdict(<type 'int'>, {})
>>> print d[0]["x"]
0

Python 2.7以降、 Counterを使用したさらに優れたソリューション があります。

>>> from collections import Counter
>>> c = Counter()
>>> c["goodbye"]+=1
>>> c["and thank you"]=42
>>> c["for the fish"]-=5
>>> c
Counter({'and thank you': 42, 'goodbye': 1, 'for the fish': -5})

いくつかのボーナス機能

>>> c.most_common()[:2]
[('and thank you', 42), ('goodbye', 1)]

詳細については、「 PyMOTW-コレクション-コンテナデータタイプ 」および「 Pythonドキュメント-コレクション 」を参照してください。

48
yanjost

partialを使用すると、少しエレガントになります。

import functools
dd_int = functools.partial(defaultdict, int)
defaultdict(dd_int)

もちろん、これはラムダと同じです。

28
Katriel

参考のために、次の方法で汎用のネストされたdefaultdictファクトリーメソッドを実装できます。

from collections import defaultdict
from functools import partial
from itertools import repeat


def nested_defaultdict(default_factory, depth=1):
    result = partial(defaultdict, default_factory)
    for _ in repeat(None, depth - 1):
        result = partial(defaultdict, result)
    return result()

深さは、default_factoryで定義されたタイプが使用される前のネストされた辞書の数を定義します。例えば:

my_dict = nested_defaultdict(list, 3)
my_dict['a']['b']['c'].append('e')
6
Campi

他の人は、以下を機能させる方法についてのあなたの質問に正しく答えています。

for x in stuff:
    d[x.a][x.b] += x.c_int

別の方法は、キーにタプルを使用することです。

d = defaultdict(int)
for x in stuff:
    d[x.a,x.b] += x.c_int
    # ^^^^^^^ Tuple key

このアプローチの良いところは、シンプルで簡単に拡張できることです。 3レベルの深さのマッピングが必要な場合は、キーに3項目のタプルを使用します。

6