>我有一个从 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 的实例中。
这有效,但不会修剪任何内容,即捕获每个部分,但捕获所有其他部分(字段、元素)。这可能是 compsci 101,但我主要是自学,所以我需要学习这种排序算法。任何关于改进这一点的意见都值得赞赏。
编辑:事实证明,这比我预期的更深入,并且抽象地更像是一个学习如何浏览任意数据结构并选择我想要或需要的东西的机会
试试这个,假设你想让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
将只包含原子属性。
或者,如果您希望dicts
t.sections
的元素而不是更多的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
的实例应该是什么样子的字典。
出的解决方案:
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的。