0

我有一个从 yaml 配置文件返回的字典,它有 4 个级别:

项目、部分、字段、元素

{
    "tag": "test", 
    "sections": [
        {
            "info": "This is section ONE", 
            "tag": "s1"
        }, 
        {
            "info": "This is section TWO", 
            "fields": [
                {
                    "info": "This is field ONE", 
                    "tag": "f1"
                }, 
                {
                    "info": "This is field TWO", 
                    "tag": "f2", 
                    "elements": [
                        {
                            "info": "This is element", 
                            "tag": "e1", 
                            "type_of": "text_field"
                        }, 
                        {
                            "info": "This is element", 
                            "tag": "e2", 
                            "type_of": "text_field"
                        }, 
                        {
                            "info": "This is element", 
                            "tag": "e3", 
                            "type_of": "text_field"
                        }, 
                        {
                            "info": "This is element", 
                            "tag": "e4", 
                            "type_of": "text_field"
                        }
                    ]
                }, 
                {
                    "info": "This is field THREE", 
                    "tag": "f3", 
                    "elements": [
                        {
                            "info": "This is element", 
                            "tag": "e5", 
                            "type_of": "text_field"
                        }, 
                        {
                            "info": "This is element", 
                            "tag": "e6", 
                            "type_of": "text_field"
                        }, 
                        {
                            "info": "This is element", 
                            "tag": "e7", 
                            "type_of": "text_field"
                        }, 
                        {
                            "info": "This is element ONE", 
                            "tag": "e8", 
                            "type_of": "text_field"
                        }
                    ]
                }
            ], 
            "tag": "s2"
        }, 
        {
            "info": "This is section THREE", 
            "fields": [
                {
                    "info": "This is field FOUR", 
                    "tag": "f4"
                }, 
                {
                    "info": "This is field FIVE", 
                    "tag": "f5"
                }, 
                {
                    "info": "This is field SIX", 
                    "tag": "f6"
                }
            ], 
            "tag": "s3"
        }
    ],
    "type_of": "custom"
}

class T():

    def __init__(self):
        self.sections = []
        self.fields = []
        self.elements = []

def rt(y):
    t = T()

    def recurse(y):
        for k,v in y.iteritems(): 
            if isinstance(v, list):
                getattr(t, k).append(v)
                [recurse(i) for i in v]
            else:
                setattr(t, k, v)
    recurse(y)
    return t

所以我需要递归一个包含字典列表的字典列表等。al.,将它们分类为它们的类型(然后添加对其所属片段的引用,但一次一个问题。)并放入 T 的实例中。

这可行,但不会删除任何内容,即捕获每个部分,但捕获所有其余部分(字段、元素)。这可能是comp sci 101,但我主要是在自学,所以这是我需要学习的某种排序算法。任何关于改进这一点的意见表示赞赏。

编辑:事实证明这比我预期的更深入,并且抽象地更多的是学习如何遍历任意数据结构并挑选出我想要或需要的东西的机会

4

2 回答 2

0

试试这个,假设你想再次sections成为实例的元素。T

def rt(y, levels=1):
    t = T()
    for (k, v) in y.iteritems(): 
        if isinstance(v, list):
            if levels > 0:
                v = [rt(i, levels-1) if isinstance(i, dict) else i for i in v]
                setattr(t, k, v)
        else:
            setattr(t, k, v)
    return t

(编辑以考虑非字典元素列表,并在一定数量的“级别”后停止迭代)

这会将嵌套字典转换为 的嵌套实例的层次结构T,并为字典中的每个项目创建属性。使用该level参数,您可以调整递归的“深度”:只要level==0只包含原子属性。

或者,如果您希望 的元素t.sections代替dicts的更多实例T

def rt(y):
    t = T()
    for (k, v) in y.iteritems(): 
        if isinstance(v, list):
            # remove list elements from dicts in list
            v = [dict((k1, v1) for (k1, v1) in i.iteritems() if not isinstance(v1, list)) 
                 if isinstance(i, dict) else i for i in v]
        setattr(t, k, v)
    return t

如果这仍然不是您的想法,请提供一个具体示例,说明T某些字典的实例应该如何。

于 2012-09-21T14:55:52.693 回答
0

我想出的解决方案:

class Tree:
    def __init__(self, node, cargo, parent=None):
        self.node = node
        self.cargo = cargo
        self.parent  = parent
    def __str__(self):
        return str(self.cargo)

from copy import copy
def just_part(y):
    z = copy(y)
    for k,v in z.items():
        if isinstance(v, list):
            del z[k]
    return z

def rt(y):
    tt = []
    s = Tree( id(y), just_part(y) )
    tt.append(s)
    def recurse(y):
        for k,v in y.iteritems(): 
            if isinstance(v, list):
                [tt.append( Tree(id(i), just_part(i), id(y) ) ) for i in v]
                [recurse(i) for i in v]
            else:
                pass
    recurse(y)
    return tt

我只是运行 rt(我的嵌套字典),这会返回一个节点列表,到目前为止,这似乎足以作为我正在做的事情的开始,而且我知道它可以以更有效的方式完成。也有这个:http ://code.activestate.com/recipes/577982-recursively-walk-python-objects/ ,但它并没有解决所有问题,而我自己的解决方案可能不是目前最pythonic的作品。

于 2012-09-26T15:41:20.123 回答