2

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

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}}. ETC...

我想我需要挖掘到最大深度并在我回到关卡时开始对值求和,但我对 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

这似乎起到了作用,尽管我作弊并进行类型检查(这几乎是你能得到的最不符合标准的),而且我假设字典中只有整数和键。我会注意到这种方法适用于分布不均匀的树。

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

您可以检查字典的最大深度,如使用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
于 2012-07-17T02:59:23.087 回答
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

如果有人感兴趣,我修改了@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 回答