4

我试图遍历一个字典,其中一些键将其他字典作为值,其中一些值是它作为值的字典的键。我正在使用 pyyaml 解析一个超过 5000 行的 YAML 文件。当我加载它时,它会创建文件中所有内容的字典,并将所有子级别分解为它们自己的字典。

这是我现在使用的,它让我得到的只是不是字典本身而是字典的键和值的东西的键和值:

for k1,v1 in dataMap['eng'].items():
    if type(dataMap['eng'][k1]) == dict:
        for k2, v2 in dataMap['eng'][k1].items():
            if type(dataMap['eng'][k1][k2]) == dict:
                for k3, v3 in dataMap['eng'][k1][k2].items():
                    if type(dataMap['eng'][k1][k2][k3]) == dict:
                        print "key: {}, val: {}".format(k3, v3)
                    else:
                        print "key: {}, val: {}".format(k3, v3)
            else:
                print "key: {}, val: {}".format(k2, v2)
    else:
        print "key: {}, val: {}".format(k1, v1)

其中“eng”是在 YAML 文件中包含所有其他内容的最顶层。下面是正在使用的 YAML 文件的示例。实际文件中有超过 5000 行

eng:
  value1: 
    v1: USA
    v2: Canada
    v3: Mexico
  value2:
    value3:
       value4: "some text here"
       value5:
          value6: "some text here"
          value7: " some other text here"
       value8: "some text here"
    etc..

像这样继续下去。有些键只有值,有些键有字典,而字典本身也有字典,这可以深入几个层次。我只是想知道是否有更好、更简单的方法来做到这一点,然后我用所有的 for 循环和 if 语句检查它是否是 dict 来处理它。最后我只需要这样的东西:

v1: USA
v2: Canada
v3: Mexico
value4: "some text here"
value6: "some text here"
value7: " some other text here"
value8: "some text here"
4

1 回答 1

8

听起来你想要一个使用递归的解决方案:

def recurse( x ):
  for k, v in x.items():
    if isinstance( v , dict ):
      recurse( v )
    else:
      print "key: {}, val: {}".format(k, v) 

请注意,如果您走得太深,递归将导致堆栈溢出。但是,该限制通常比您在这里所期望的要高得多:

>>> import sys
>>> sys.getrecursionlimit()
1000
>>> def f(i):
      f(i+1)
>>> f(1)
...
File "<stdin>", line 3, in f
File "<stdin>", line 3, in f
File "<stdin>", line 3, in f
RuntimeError: maximum recursion depth exceeded

但是,如果您正在编写一个程序,其中有人可以恶意制作文件并使您的解析器崩溃(引发异常),那么您应该考虑将递归转换为迭代,这总是可能的。折衷是递归代码非常易于读写,而迭代转换有时则略逊一筹。

于 2013-06-11T18:44:32.783 回答