Python 递归遍历字典

Python 递归遍历字典,python,recursion,dictionary,python-2.7,Python,Recursion,Dictionary,Python 2.7,我需要递归遍历字典,并记住前面的键 让我解释一下: dic = {u'resources': {u'info': {u'load': (u'37', u'17')}}, u'peak': {u'load': (u'0', u'1')}} 元素在达到某个值之前始终是一个值或一个字典。 我想这样打印上面的dic(省略下面的xxx,它最终应该是两个值的差值) 这是我目前掌握的代码: def convertToTable(var): if isinstance(var, tuple):

我需要递归遍历字典,并记住前面的键

让我解释一下:

dic = {u'resources': {u'info': {u'load': (u'37', u'17')}}, u'peak': {u'load': (u'0', u'1')}}
元素在达到某个值之前始终是一个值或一个字典。 我想这样打印上面的
dic
(省略下面的xxx,它最终应该是两个值的差值)

这是我目前掌握的代码:

def convertToTable(var):
    if isinstance(var, tuple):
        if len(var) != 2:
            return str(var)

        v1, v2 = var
        try:
            v1 = float(v1)
            v2 = float(v2)
        except ValueError:
            pass
        if type(v1) != type(v2):
            return '\t%s\t%s\n' % (v1, v2)
        elif isinstance(v1, int) or isinstance(v1, float):
            sign = '+' if v2 - v1 > 0 else ''
            return '\t%s\t%s\t%s%s\n' % (v1, v2, sign, v2 - v1)
        elif isinstance(v1, list):
            ret = ''
            for i in range(max(len(v1), len(v2))):
                v1v = v1[i] if i < len(v1) else ''
                v2v = v2[i] if i < len(v2) else ''
                ret += '\t%s, %s\n' % (v1v, v2v)
            return ret
        else:
            return '\t%s\t%s\n' % (v1, v2)
    elif isinstance(var, dict):
        ret = ''
        for key, value in var.iteritems():
            # fix this crap, it's not printing all recursive levels of keys!
            ret += '%s %s' % (key, convertToTable(value))
        return ret
    else:
        return '%s\n' % (var)
def可转换(var):
如果isinstance(变量、元组):
如果len(var)!=2:
返回str(var)
v1,v2=var
尝试:
v1=浮动(v1)
v2=浮动(v2)
除值错误外:
通过
如果类型(v1)!=类型(v2):
返回“\t%s\t%s\n%”(v1,v2)
elif isinstance(v1,int)或isinstance(v1,float):
符号=“+”如果v2-v1>0,则为“其他”
返回“\t%s\t%s\t%s%s\n%”(v1,v2,sign,v2-v1)
elif isinstance(v1,列表):
ret=''
对于范围内的i(最大值(len(v1),len(v2)):
v1v=v1[i]如果i
我不知道如何再次将前面的键递归地传递给函数!要么我得到一张额外的钥匙印,要么什么都没有!(请不要建议我使用
json.dumps
,因为它并不能真正满足我的需要!)
我希望有人能检查我的解决方案,并指出其中的缺陷

我不确定您的代码出了什么问题,但这可能会满足您的要求:

def iteritems_recursive(d):
  for k,v in d.iteritems():
    if isinstance(v, dict):
      for k1,v1 in iteritems_recursive(v):
        yield (k,)+k1, v1
    else:
      yield (k,),v

dic = {u'resources': {u'info': {u'load': (u'37', u'17')}, u'peak': {u'load': (u'0', u'1')}}}

for p,v in iteritems_recursive(dic):
  print p, "->", v
iteritems\u recursive
迭代传入的字典,并返回一个
(路径,值)
元组。路径本身就是一个元组,描述到达该项的键

上述代码打印:

(u'resources', u'info', u'load') -> (u'37', u'17')
(u'resources', u'peak', u'load') -> (u'0', u'1')
如果要打印表格,请将上面的for循环替换为:

for p,v in iteritems_recursive(dic):
  diff = float(v[0]) - float(v[1])
  p = ''.join('{:10}'.format(w) for w in p)
  v = ''.join('{:5}'.format(f) for f in v)
  print p, v, diff
其中打印:

resources info      load       37   17    20.0
resources peak      load       0    1     -1.0

我有两个解决方案,第一个方案将所有关键点的名称带到各个级别,并在返回堆栈之前在底部打印它们

第二种是在下降的过程中打印出来的,这样就避免了“记住”水平

import sys

dic = {u'resources':
            {u'info':
                {u'load': (u'37', u'17')}
            },
       u'peak':
            {u'load': (u'0', u'1')}
      }


def racecar(goomba, levels=None):
    if levels == None:
        levels = []
    for key in goomba:
        if type(goomba[key]) is dict:
            levels.append(key)
            levels = racecar(goomba[key], levels)
        else:
            levels.append(key)
            for name in levels:
                sys.stdout.write(name + ' ')
            for val in goomba[key]:
                sys.stdout.write(val + ' ')
            sys.stdout.write('xxx\n')
            return []


def racecar2(goomba):
    for key in goomba:
        sys.stdout.write(key + ' ')
        if type(goomba[key]) is dict:
            racecar(goomba[key])
        else:
            for val in goomba[key]:
                sys.stdout.write(val + ' ')
            sys.stdout.write('xxx\n')

racecar(dic)
racecar2(dic)
返回:

peak load 0 1 xxx
resources info load 37 17 xxx

子项可以是类型列表或dict?键
level1
的值为类型dict,但
level2B
level3B
的值为dict列表。
level1
是否可以/应该是一个包含单个dict的列表?@fabian,对不起,我弄错了示例。子元素总是一个元素或一个元素tuple@theAlse什么是元素?你能更新你的帖子吗?对不起,伙计们,我把这个例子搞砸了。请看更新的一个!感谢您的回复,您的两种解决方案都不正确!几乎同样地,我的观点是错误的。你已经运行它们并检查了打印,它甚至没有打印所有元素!问题中指定的输出似乎没有反映提供的输入。你期望得到什么样的输出?哎呀,我错过了加载元素,现在修复了。我希望有人能指出我解决方案中的缺陷。我不知道我要如何修改这个代码才能得到一个不同的值。啊,我误解了你们的问题,因为你们并没有问一个。您可能想要编辑您的帖子并包含一个特定的问题。什么是“价值差异”?给定示例输入,您希望输出看起来像什么?我指的是每个项目提供的两个值之间的差异,但这很容易从代码中获得。我接受您的解决方案,因为它是最简单、最容易理解的
import sys

dic = {u'resources':
            {u'info':
                {u'load': (u'37', u'17')}
            },
       u'peak':
            {u'load': (u'0', u'1')}
      }


def racecar(goomba, levels=None):
    if levels == None:
        levels = []
    for key in goomba:
        if type(goomba[key]) is dict:
            levels.append(key)
            levels = racecar(goomba[key], levels)
        else:
            levels.append(key)
            for name in levels:
                sys.stdout.write(name + ' ')
            for val in goomba[key]:
                sys.stdout.write(val + ' ')
            sys.stdout.write('xxx\n')
            return []


def racecar2(goomba):
    for key in goomba:
        sys.stdout.write(key + ' ')
        if type(goomba[key]) is dict:
            racecar(goomba[key])
        else:
            for val in goomba[key]:
                sys.stdout.write(val + ' ')
            sys.stdout.write('xxx\n')

racecar(dic)
racecar2(dic)
peak load 0 1 xxx
resources info load 37 17 xxx