2

辞書のさまざまなレベルで値のカウントを取得できる関数を定義しようとしています。たとえば、次のようなものがあるとします。

vehicles = {
    'Ford': {
        'Falcon': {
            '2008': 10, 
            '2009': 12, 
            '2010': 5
        }
    }, 
    'Holden': {
        'Commodore': {
            '2008': 15, 
            '2009': 11, 
            '2010': 5
        }
    }
}

各深さの値を計算する関数を呼び出せるようにしたいと思います。したがって、深さ 0 では、関数はすべての値の合計 (58) を返します。深さ 1 では、関数は dict を返し{'Ford': 27, 'Holden': 31}ます。深さ 2 では、関数は dict を返し{'Ford': {'Falcon': 27}, 'Holden': {'Commodore': 31}}ます。等...

最大の深さまで掘り下げて、レベルを上げて値を合計し始める必要があると思いますが、私は Python にかなり慣れていないので苦労しています。おそらく再帰を使用する必要がありますか?

ご協力いただきありがとうございます。

4

5 に答える 5

2

十分にテストされていない私の解決策


def sum_values(data):
    if type(data.values()[0]) != dict:
        return sum(data.values())
    else:
        return sum(sum_values(v) for v in data.values())

def depth_values(data, depth = 0):
    if depth == 0:
        return sum_values(data)
    else:
        return dict(
            (k, depth_values(v, depth-1))
            for k, v in data.items()
        )

テスト:


print depth_values(vehicles, 0) # >> 58
print depth_values(vehicles, 1) # >> {'Holden': 31, 'Ford': 27}
print depth_values(vehicles, 2) # >> {'Holden': {'Commodore': 31}, 'Ford': {'Falcon': 27}}
print depth_values(vehicles, 3) # exceptions
于 2012-07-17T03:07:56.000 に答える
1

これはトリックを行うようですが、私は少しごまかして型チェックを行います (これは、あなたが得ることができるのと同じくらい非Pythonicです)。さらに、辞書にはintとキーしかないと仮定しています。このアプローチは、不均一に分散されたツリーで機能することに注意してください。

def score(n):
    if type(n) == int:
        return n
    else:
        return sum([score(n[x]) for x in n])

def fold_dict(xs, d):
    if d == 1:
        if type(xs) == int:
            return xs            
        return {n: score(xs[n]) for n in xs}
    else:
        if type(xs) == int:
            return xs    
        return {n: fold_dict(xs[n], d - 1) for n in xs}

入力、出力の例:

>>> y = {'a': {'a1': {'a11': 5, 'a12': 2, 'a13': 8}, 'a2': 6}, 'b': 7, 'c': {'c1': 18, 'c2': 1}}
>>> fold_dict(y, 1)
{'a': 21, 'c': 19, 'b': 7}
>>> fold_dict(y, 2)
{'a': {'a1': 15, 'a2': 6}, 'c': {'c2': 1, 'c1': 18}, 'b': 7}
于 2012-07-17T03:13:46.263 に答える
0
def values_at_depth(d, depth):
    if depth == 0:
        sum = 0
        for k, v in d.iteritems():
            if hasattr(v, "keys"):
                sum += values_at_depth(v, 0)
            else:
                sum += v
        return sum
    else:
        ret = {}
        for k, v in d.iteritems():
            ret[k] = values_at_depth(v, depth-1)
        return ret
于 2012-07-17T03:08:56.973 に答える
0

isinstanceとを使用して、辞書の最大深度を確認できますrecursion

例えば、

depth = 0
dict = { ... }
def find_depth(dict):
    # dict = { ... }
    for key in dict:
        if isinstance(dict[key], dict):
            depth += 1
            find_depth(dict[key])
            break
于 2012-07-17T02:59:23.087 に答える
0

誰かが興味を持っている場合は、 @Ned Batchelder の関数を変更して、値の合計を報告するだけでなく、さまざまな深さのキーの数も報告するタプルを返します。うまくいけば、それは理にかなっています...

とにかく、ここにあります:

def values_at_depth(d, depth = 0):
    if depth == 0:
        sumVal = 0
        sumKey = 0
        for k, v in d.iteritems():
            if hasattr(v, "keys"):
                sumKey += collectCnt(v, 0)[0]
                sumVal += collectCnt(v, 0)[1]
            else:
                sumVal += v
                sumKey += 1
        return (sumKey,sumVal)
    else:
        ret = {}
        for k, v in d.iteritems():
            ret[k] = collectCnt(v, depth-1)
        return ret

PS。この追加情報をどこに置くべきかわかりませんでした。それが別の場所にある場合は、私に知らせてください。

于 2012-07-18T02:52:35.173 に答える