在Python中,如果节点位于树的深处,如何分配节点的子节点?
我有描述树(父-子)的数据。我想在此基础上构建一个JSON文件,并在树中找到父级的任何位置分配父级的子级 这个问题是这个答案的延伸: 代码:在Python中,如果节点位于树的深处,如何分配节点的子节点?,python,json,Python,Json,我有描述树(父-子)的数据。我想在此基础上构建一个JSON文件,并在树中找到父级的任何位置分配父级的子级 这个问题是这个答案的延伸: 代码: file = [ ('parent1', ['child1', 'child2', 'child3']), ('parent2', ['child4', 'child5', 'child6']), ('child1', ['child7', 'child8']), ('child5', ['child10', 'c
file = [
('parent1', ['child1', 'child2', 'child3']),
('parent2', ['child4', 'child5', 'child6']),
('child1', ['child7', 'child8']),
('child5', ['child10', 'child33']),
('parent3', ['child1', 'child2', 'child3'])
]
json_dict = {}
flat_dict = {}
for parent, children in file:
if parent in flat_dict:
value = flat_dict[parent]
else:
value = {}
flat_dict[parent] = json_dict[parent] = value
for child in children:
flat_dict[child] = value[child] = {}
{
"parent1": {
"child1": {
"child7": {},
"child8": {}
},
"child2": {},
"child3": {}
},
"child1": {},
"child2": {},
"child3": {},
"parent2": {
"child4": {},
"child5": {
"child10": {},
"child33": {}
},
"child6": {}
},
"child4": {},
"child5": {
"child10": {},
"child33": {}
},
"child6": {},
"child7": {},
"child8": {},
"child10": {},
"child33": {},
"parent3": {
"child1": {},
"child2": {},
"child3": {}
}
}
{'parent1': {'child1': {'child7': {}, 'child8': {}}, 'child2': {}, 'child3': {}}, 'parent2': {'child4': {}, 'child5': {'child10': {}, 'child33': {}}, 'child6': {}}, 'parent3': {'child1': {'child7': {}, 'child8': {}}, 'child2': {}, 'child3': {}}}
电流输出:
file = [
('parent1', ['child1', 'child2', 'child3']),
('parent2', ['child4', 'child5', 'child6']),
('child1', ['child7', 'child8']),
('child5', ['child10', 'child33']),
('parent3', ['child1', 'child2', 'child3'])
]
json_dict = {}
flat_dict = {}
for parent, children in file:
if parent in flat_dict:
value = flat_dict[parent]
else:
value = {}
flat_dict[parent] = json_dict[parent] = value
for child in children:
flat_dict[child] = value[child] = {}
{
"parent1": {
"child1": {
"child7": {},
"child8": {}
},
"child2": {},
"child3": {}
},
"child1": {},
"child2": {},
"child3": {},
"parent2": {
"child4": {},
"child5": {
"child10": {},
"child33": {}
},
"child6": {}
},
"child4": {},
"child5": {
"child10": {},
"child33": {}
},
"child6": {},
"child7": {},
"child8": {},
"child10": {},
"child33": {},
"parent3": {
"child1": {},
"child2": {},
"child3": {}
}
}
{'parent1': {'child1': {'child7': {}, 'child8': {}}, 'child2': {}, 'child3': {}}, 'parent2': {'child4': {}, 'child5': {'child10': {}, 'child33': {}}, 'child6': {}}, 'parent3': {'child1': {'child7': {}, 'child8': {}}, 'child2': {}, 'child3': {}}}
预期输出:
我希望所有child1
节点如下:
"child1": {
"child7": {},
"child8": {}
}
但正如我们所看到的,只有在
parent1
节点中,它才保留其子节点。希望这是您想要的
代码:
relations = []
for k,l in file:
for v in l:
relations.append((k,v))
pop_list=[]
items = {}
for parent, child in relations:
parent_dict = items.setdefault(parent, {})
child_dict = items.setdefault(child, {})
if child not in parent_dict:
parent_dict[child] = child_dict
pop_list.append(child)
for child in pop_list:
if child in items.keys():
items.pop(child)
print(items)
输出:
file = [
('parent1', ['child1', 'child2', 'child3']),
('parent2', ['child4', 'child5', 'child6']),
('child1', ['child7', 'child8']),
('child5', ['child10', 'child33']),
('parent3', ['child1', 'child2', 'child3'])
]
json_dict = {}
flat_dict = {}
for parent, children in file:
if parent in flat_dict:
value = flat_dict[parent]
else:
value = {}
flat_dict[parent] = json_dict[parent] = value
for child in children:
flat_dict[child] = value[child] = {}
{
"parent1": {
"child1": {
"child7": {},
"child8": {}
},
"child2": {},
"child3": {}
},
"child1": {},
"child2": {},
"child3": {},
"parent2": {
"child4": {},
"child5": {
"child10": {},
"child33": {}
},
"child6": {}
},
"child4": {},
"child5": {
"child10": {},
"child33": {}
},
"child6": {},
"child7": {},
"child8": {},
"child10": {},
"child33": {},
"parent3": {
"child1": {},
"child2": {},
"child3": {}
}
}
{'parent1': {'child1': {'child7': {}, 'child8': {}}, 'child2': {}, 'child3': {}}, 'parent2': {'child4': {}, 'child5': {'child10': {}, 'child33': {}}, 'child6': {}}, 'parent3': {'child1': {'child7': {}, 'child8': {}}, 'child2': {}, 'child3': {}}}
一种方法是对链接的答案添加一个简单的修改,检查是否已经存在子项,并使用现有的对象
json_dict = {}
flat_dict = {}
for parent, children in file:
if parent in flat_dict:
value = flat_dict[parent]
else:
value = {}
flat_dict[parent] = json_dict[parent] = value
for child in children:
if child in flat_dict:
value[child] = flat_dict[child]
else:
flat_dict[child] = value[child] = {}
在这两种情况下,代码都可以通过使用来缩短,但我通常不会使用,因为它会创建一个空字典实例,即使这不是必需的:
json_dict = {}
flat_dict = {}
for parent, children in file:
if parent in flat_dict:
value = flat_dict[parent]
else:
value = json_dict[parent] = flat_dict[parent] = {}
for child in children:
value[child] = flat_dict.setdefault(child, {})
虽然第二个解决方案执行一些可能不必要的操作,但代码看起来更清晰
同样干净但不必要对象较少的替代方案使用:
除了需要导入外,此解决方案的打印效果不如基于常规dict的解决方案干净。但是,这不会以任何方式影响到JSON的转换
由于您评论说实际上不希望在根中包含子节点,因此此处显示的代码段将仅将父节点放置在根中。但是,如果您稍后发现某个节点是子节点,则它们不会从根节点中删除该节点。这可以通过另一个简单的修改来实现,这里显示的是defaultdict
示例,但也适用于所有其他示例:
from collections import defaultdict
json_dict = {}
flat_dict = defaultdict(dict)
for parent, children in file:
if parent in flat_dict:
value = flat_dict[parent]
else:
value = json_dict[parent] = flat_dict[parent]
for child in children:
value[child] = flat_dict[child]
json_dict.pop(child, None)
下面是一个有最终答案的例子
请记住,此代码不会检查循环引用。循环引用将自动从结果中删除自身。例如:
file = [
('A', ['B']),
('B', ['C']),
('C', ['A']),
]
所以你不想要父节点?实际上我需要所有的。我需要保留在树中任何位置找到的任何节点的子节点。您确定这些节点始终命名为父节点和子节点吗?有一个很简单的问题,你可能在这里错过了,伙计。我只是把他们命名为家长和孩子,以便澄清,否则他们都有一个特定的ID。我注意到你有很多问题,人们已经回答了,但你没有选择任何答案。当答案满足您的需要时,您应该单击它旁边的复选标记。这会给所有相关人员打分,更重要的是,将您的问题从未回答的队列中删除。您只能选择一个答案,但可以对所有答案进行投票。非常感谢您提供的解决方案和解释。一切似乎都很好,两个答案都很好。但是在运行了更多的测试之后,当我添加这些数据时,您的代码中没有一个可以绕过该测试:('child9',[]),('child8',['child9','B','C'])。问题是,当根节点“child9”以后成为子节点时,它不会被其他代码删除。在上一段代码中,您提到了这种情况,它删除了它,但它会将其他子节点带到根节点。e、 g.“儿童2”和“儿童5”。但所有这些可能性都与@lazycoder解决方案有关。@jesy2013。谢谢你接电话。我已经对我的代码做了一些修复。我试图在不考虑后果的情况下缩短代码。应该不会再有丢失的角落箱子了。谢谢你。这也是一个很好的简短解决方案。