从python迭代嵌套的yaml字典

时间:2019-03-14 16:55:32

标签: python python-3.x dictionary iterator yaml

我通过解析类似于以下格式的yaml文档来安全地加载了python对象,

  

envdata = yaml.safe_load(data)

id: XXX
name: XXX
tecVersion: 1

wrapper: #category
    wrapper-box-1: #instance
        host: XXX
        port: 4567
        tags:
          - ABC
          - VTR


powerWrapper: #category
     pw-box-45: #instance
         host: YYY
         port: 7890
         tags:
           - ABC

每个类别都是顶级数组对象,实例是类别内部的数组对象。

给定标签ex的要求是:ABC,我想将每个类别中所有匹配的实例作为列表。如何遍历每个元素并比较标签,并以最佳方式将所有匹配的实例添加到实例数组中?

1 个答案:

答案 0 :(得分:0)

  

(1。)每个类别都是一个顶级数组对象,实例是该类别内的一个数组对象。

     

(2。)我如何...比较标签并将所有匹配的实例添加到实例数组中……?

(1。)中的定义并不十分出色,但足以使用。 我不同意您使用“数组”或“ list”一词,而该类别所包含的显然是“地图”或“ dict”。 我认为,如果保证每个实例都包含一个名为'instance''id'或类似名称的密钥,将它们与诸如'tecVersion'之类的同级条目区分开,那就更好了。 或者,可以将所有实例向下推到带有广告素材名称的键下,例如,让我们将其命名为'instances'吗?

您已经清楚地表明'wrapper'是一个“类别”。 我不知道叫'wrapper-box-1'是什么。 太糟糕了,您还没有在示例数据中包含'wrapper-box-2'

yaml返回的内容是

>>> pprint.pprint(envdata)
{'id': 'XXX',
 'name': 'XXX',
 'powerWrapper': {'pw-box-45': {'host': 'YYY', 'port': 7890, 'tags': ['ABC']}},
 'tecVersion': 1,
 'wrapper': {'wrapper-box-1': {'host': 'XXX',
                               'port': 4567,
                               'tags': ['ABC', 'VTR']}}}

好,让我们迭代一下:

def get_tags(putative_category):
    """Generator, returns tags if the input appears to be a category."""
    try:
        for undefined_box_concept, attributes in putative_category.items():
            tags = attributes['tags']
            yield tags
    except (AttributeError, KeyError):
        pass

for category_name, category in envdata.items():
    for tags in get_tags(category):
        print(tags, category_name, category)

输出:

['ABC', 'VTR'] wrapper {'wrapper-box-1': {'host': 'XXX', 'port': 4567, 'tags': ['ABC', 'VTR']}}
['ABC'] powerWrapper {'pw-box-45': {'host': 'YYY', 'port': 7890, 'tags': ['ABC']}}

您的问题陈述含糊其词。 一旦有了标签,对我来说不清楚您要如何处理它们。 对于(2.),使用我提供的生成器,具有嵌套for循环的列表理解就足够了。