递归字典列表字典等等(python)

时间:2012-09-21 14:36:55

标签: python parsing sorting recursion

我有一个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

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

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

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

2 个答案:

答案 0 :(得分: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

(编辑以考虑非dict元素的列表,并在一定数量的'级别'之后停止迭代)

这会将嵌套字典转换为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的实例应该如何用于某些词典。

答案 1 :(得分: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的作品。