2013-05-05 4 views
6

私のコードは、現在、別のものに多額のネストされたdictで物事をカウントしています。私は、3つの値でインデックスを作成し、次に数える必要があるアイテムを持っています。私はそのようなタイトなループ内のアイテムをカウントすることができますよりPython的な方法

from collections import defaultdict 

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

:だから、私のループの前に、私はそうのようなネストされたdefaultdictを初期化

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

私はこれらすべてのdefaultdict Sを初期化するように感じますJavaのような型で型宣言を作るのが好きです。このようなことをするもっと慣れ親しんだ/ピトンの方法がありますか?

答えて

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 
3

あなたは物事を数えているので、あなたは最も内側のdictのためのカウンタを使用する必要があります。カウンターを使用して

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) 

を使用すると、most_commonとして有用な方法にアクセスできるようになります。

あなたはこの辞書をどうするつもり内容に応じて、あなたは深いネスティングを必要としない場合があります。代わりに、キーのタプルを使用できます。例えば、

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}) 
2

を生み出します条件が満たされているか、条件によって異なる値が追加されている可能性がありますか?そうでなければ、必ず各カウンタの値は常に1になるでしょうか?

私は考えることができる最も簡単な解決策は、わずか3つのループ値のタプルをキー単一の辞書を作成することである、と述べました。たとえば、次のようなものがあります。

dict(((a,b,c),1) for a in A for b in B for c in C) 

しかし、これはちょうど各カウンターに1つを与えます。あなたは、BCの値に応じて、より適切な何かを返すいくつかの条件または関数呼び出しと、上記の式にを交換する必要があります。

0

私は同様の必要性を持っていた、と次のように作成しました:

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) 

私はそれを更新して終了した場合、私はその要旨も作成しました:https://gist.github.com/KyleJamesWalker/8573350

関連する問題