0

次のようなCounter()クラスを作成するための洗練された方法を見つけるのに問題があります。

  • 任意の数のキーを入力し、このキーのリストに基づいてネストされた辞書を返します。
  • このネストされた辞書の増分も任意です。

例えば:

counter = Counter()
for line in fin:
    if a:
        counter.incr(key1, 1)
    else:
        counter.incr(key2, key3, 2)
print counter

理想的には、{key1:20、{key2:{key3:40}}}のような結果が得られることを望んでいます。しかし、私はキーのリストからこの任意のネストされた辞書を作成することに固執しています。どんな助けでも大歓迎です。

4

3 に答える 3

0

オブジェクトに存在できる唯一のタイプの値Counterはintであり、ネストされたディクショナリを。で表すことはできませんCounter

これを通常の辞書(counter = {})で行う1つの方法があります。まず、更新するには、単一のキーの値をインクリメントします。

counter[key1] = counter.setdefault(key1, 0) + 1

または、ネストされた構造を作成するための任意のキーのリストの場合:

tmp = counter
for key in key_list[:-1]:
    tmp = tmp.setdefault(key, {})
tmp[key_list[-1]] = tmp.setdefault(key_list[-1], 0) + 1

私はおそらくこれを次の関数に変えるでしょう:

def incr(counter, val, *keys):
    tmp = counter
    for key in keys[:-1]:
        tmp = tmp.setdefault(key, {})
    tmp[keys[-1]] = tmp.setdefault(keys[-1], 0) + val

例:

>>> counter = {}
>>> incr(counter, 1, 'a')
>>> counter
{'a': 1}
>>> incr(counter, 2, 'a')
>>> counter
{'a': 3}
>>> incr(counter, 2, 'b', 'c', 'd')
>>> counter
{'a': 3, 'b': {'c': {'d': 2}}}
>>> incr(counter, 3, 'b', 'c', 'd')
>>> counter
{'a': 3, 'b': {'c': {'d': 5}}}
于 2013-03-14T20:19:12.373 に答える
0

サブクラスdict化して、独自のネストされた構造を作成できます。

これがそのようなクラスを書くための私の試みです:

class Counter(dict):
    def incr(self, *args):
        if len(args) < 2:
            raise TypeError, "incr() takes at least 2 arguments (%d given)" %len(args)

        curr = self

        keys, count = args[:-1], args[-1]

        for depth, key in enumerate(keys, 1):
            if depth == len(keys):
                curr[key] = curr.setdefault(key, 0) + count
            else:
                curr = curr.setdefault(key, {})


counter = Counter()

counter.incr('key1', 1)
counter.incr('key2', 'key3', 2)
counter.incr('key1', 7)
print counter #{'key2': {'key3': 2}, 'key1': 8}
于 2013-03-14T20:20:18.887 に答える
0

2つの可能性があります。

まず、sCounterで作られた「キーパス」を持つフラットを使用することで、ネストされたキーをいつでも偽造できます。tuple

counter = Counter()
for line in fin:
    if a:
        counter.incr((key1,), 1)
    else:
        counter.incr((key2, key3), 2)

ただし、-replacementを作成する必要があります。strまたは、より適切には、を実装するラッパークラスを作成する必要があります__str__incrそして、その間、必要なAPIを正確に使用できるラッパーを簡単に作成できます。

def incr(self, *args):
    super().incr(args[:-1], args[-1])

Counterまたは、ネストされたの上に独自のクラスを作成することもできますdict。のコードCounterは純粋なPythonで記述されており、ソースは非常にシンプルで読みやすいものです。

あなたのコードから、あなたはどこのようなものにもアクセスする必要がないように見えますcounter[key2][key3]。つまり、最初のものはおそらくより単純でより適切になるでしょう。

于 2013-03-14T20:18:41.850 に答える