6

私のコードは現在、別のものに大きくネストdictされたものをカウントする必要があります。3 つの値でインデックスを作成してからカウントする必要があるアイテムがあります。したがって、ループの前に、ネストされたものを次のdefaultdictように初期化します。

from collections import defaultdict

type_to_count_dic = defaultdict(
        lambda: defaultdict(
            lambda: defaultdict(int)
        )
    )

これにより、次のようにタイトループ内のアイテムをカウントできます。

for a in ...:
    for b in ...:
        for c in ...:
            type_to_count_dic[a][b][c] += 1

これらすべてのdefaultdicts を初期化するのは、Java などで型宣言を行うのとよく似ているように感じます。このようなことを行うためのより慣用的/Python的な方法はありますか?

4

4 に答える 4

8
from collections import defaultdict

class _defaultdict(defaultdict):
    def __add__(self, other):
        return other

def CountTree():
    return _defaultdict(CountTree)

>>> t = CountTree()
>>> t['a']
defaultdict(<function CountTree at 0x9e5c3ac>, {})
>>> t['a']['b']['c'] += 1
>>> print t['a']['b']['c']
1
于 2013-05-05T12:14:56.730 に答える
3

物事を数えているので、最も内側の辞書にはカウンターを使用する必要があります。

import collections
defaultdict = collections.defaultdict
Counter = collections.Counter

x = defaultdict(lambda: defaultdict(Counter))

for a in A:
    for b in B:
        x[a][b].update(C)

Counter を使用すると、 most_commonなどの便利なメソッドにアクセスできます。

この dict で何をしようとしているかによっては、深いネストが必要ない場合があります。代わりに、キーにタプルを使用できます。例えば、

import collections
import itertools as IT

A = range(2)
B = 'XYZ'
C = 'abc'
x = collections.Counter(IT.product(A, B, C))
print(x)

収量

A = range(2)
B = 'XYZ'
C = 'abc'
x = collections.Counter(IT.product(A, B, C))
print(x)

収量

Counter({(0, 'X', 'c'): 1, (0, 'Z', 'a'): 1, (1, 'Z', 'a'): 1, (1, 'X', 'c'): 1, (1, 'Z', 'b'): 1, (0, 'X', 'b'): 1, (0, 'Y', 'a'): 1, (1, 'Y', 'a'): 1, (0, 'Z', 'c'): 1, (1, 'Z', 'c'): 1, (0, 'X', 'a'): 1, (0, 'Y', 'b'): 1, (1, 'X', 'a'): 1, (1, 'Y', 'b'): 1, (0, 'Z', 'b'): 1, (1, 'Y', 'c'): 1, (1, 'X', 'b'): 1, (0, 'Y', 'c'): 1})
于 2013-05-05T11:56:15.450 に答える
0

I had a similar need, and created the following:

import json

from collections import defaultdict


class NestedDefaultDict(defaultdict):
    def __init__(self, depth, default=int, _root=True):
        self.root = _root
        self.depth = depth
        if depth > 1:
            cur_default = lambda: NestedDefaultDict(depth - 1,
                                                    default,
                                                    False)
        else:
            cur_default = default
        defaultdict.__init__(self, cur_default)

    def __repr__(self):
        if self.root:
            return "NestedDefaultDict(%d): {%s}" % (self.depth,
                                                    defaultdict.__repr__(self))
        else:
            return defaultdict.__repr__(self)


# Quick Example
core_data_type = lambda: [0] * 10
test = NestedDefaultDict(3, core_data_type)
test['hello']['world']['example'][5] += 100
print test
print json.dumps(test)

# Code without custom class.
test = defaultdict(lambda: defaultdict(lambda: defaultdict(core_data_type)))
test['hello']['world']['example'][5] += 100
print test
print json.dumps(test)

If I end up updating it I've also created a gist: https://gist.github.com/KyleJamesWalker/8573350

于 2014-01-23T15:08:07.960 に答える