Python:获取各种dict深度的值

时间:2012-07-17 02:41:17

标签: python recursion dictionary

我正在尝试定义一个函数,它允许我在dict的各个级别获取值计数。例如,如果我有类似的东西:

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

我希望能够调用一个能够计算每个深度值的函数。因此,在深度0处,函数将返回每个值的总和(58)。在深度1处,函数将返回带有{'Ford': 27, 'Holden': 31}的字典。在深度2处,函数将返回带有{'Ford': {'Falcon': 27}, 'Holden': {'Commodore': 31}}的字典。等...

我认为我需要挖掘到最大深度并开始对值进行求值,因为我向后移动了水平,但我对Python很新,我正在努力。可能我需要使用递归?

感谢您的帮助。

5 个答案:

答案 0 :(得分: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()
        )

TEST:


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

答案 1 :(得分:1)

这似乎可以解决这个问题,虽然我做了一些欺骗并进行了类型检查(这就像你可以得到的那样是非语音的),而且我假设词典中只有整数和键。我会注意到这种方法适用于不均匀分布的树。

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}

答案 2 :(得分:0)

您可以使用isinstancerecursion

查看字典的最大深度

例如,

depth = 0
dict = { ... }
def find_depth(dict):
    # dict = { ... }
    for key in dict:
        if isinstance(dict[key], dict):
            depth += 1
            find_depth(dict[key])
            break

答案 3 :(得分: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

答案 4 :(得分: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。我不知道在哪里提供这些额外的信息。如果它应该在其他地方,请告诉我。