Python:从父子值列表创建嵌套字典
以下是输入:Python:从父子值列表创建嵌套字典,python,python-3.x,dictionary,treeview,Python,Python 3.x,Dictionary,Treeview,以下是输入: list_child_parent= [ #first value is child, second is parent (0, 1), (1, 3), (8, 7), (3, 6), (4, 3), (5, 3) ] 输出需要使用这些值创建嵌套字典树。树的深度永远不会超过6层 例如: output_dict = { 6: {3: {1: {0: {}}, 4: {}, 5: {}}}, 7: {8: {}} }
list_child_parent= [
#first value is child, second is parent
(0, 1),
(1, 3),
(8, 7),
(3, 6),
(4, 3),
(5, 3)
]
输出需要使用这些值创建嵌套字典树。树的深度永远不会超过6层
例如:
output_dict = {
6: {3: {1: {0: {}}, 4: {}, 5: {}}}, 7: {8: {}}
}
我花了两天的时间来完成这项工作。我曾尝试编写函数来查找键在树中的位置,然后在其后添加新键,但我无法生成可以继续超过3个级别的代码。这是令人困惑的,我觉得可能有一个标准库可以做到这一点
我的经验水平很低 不太好看,可能也不太像蟒蛇,但它应该能让你行动起来:
#!/usr/bin/env python3
def make_map(list_child_parent):
has_parent = set()
all_items = {}
for child, parent in list_child_parent:
if parent not in all_items:
all_items[parent] = {}
if child not in all_items:
all_items[child] = {}
all_items[parent][child] = all_items[child]
has_parent.add(child)
result = {}
for key, value in all_items.items():
if key not in has_parent:
result[key] = value
return result
if __name__ == '__main__':
list_child_parent = [
#first value is child, second is parent
(0, 1),
(1, 3),
(8, 7),
(3, 6),
(4, 3),
(5, 3)
]
actual = make_map(list_child_parent)
expected = {
6: {
3: {
1: {
0: {}
},
4: {},
5: {}
}
},
7: {
8: {}
}
}
print('OK' if expected == actual else 'FAIL')
此代码将树从给定格式转换为树结构字典。这是一个很大的失误,但它有助于跟踪正在发生的事情。就性能而言,它相当不错
LIST_CHILD_PARENTS = [
#first value is child, second is parent
(0, 1),
(1, 3),
(8, 7),
(3, 6),
(4, 3),
(5, 3)
]
class Node(object):
def __init__(self, value):
self.value = value
# List of references to Node()'s.
self.child = []
# Reference to parent Node()
self.parent = None
def set_parent(self, parent):
self.parent = parent
def set_child(self, child):
self.child.append(child)
def get_a_root(items):
"""Find a root node from items.
Grab some node and follow the parent pointers to a root.
"""
cur_key = list(items.keys())[0]
while items[cur_key].parent is not None:
cur_key = items[cur_key].parent.value
parent = items[cur_key]
return parent
def extract_tree(items, root):
"""Remove the tree from root in items.
"""
cur_key = root.value
this_node = items[cur_key]
if len(this_node.child) == 0:
items.pop(cur_key)
return
else:
for child in this_node.child:
extract_tree(items, child)
items.pop(cur_key)
def insert_from_root(tree, root):
"""Insert the dictionary items from a tree.
"""
current = root
if len(current.child) == 0:
tree[current.value] = {}
return
else:
table = {}
for child in current.child:
insert_from_root(table, child)
tree[current.value] = table
def build_graphs():
"""Map all input graphs into Node(object)'s.
Return: A hash table by value: Node(value, child, parent)
"""
items = {}
for child, parent in LIST_CHILD_PARENTS:
if not child in items:
c_n = Node(child)
items[child] = c_n
else:
c_n = items[child]
if not parent in items:
p_n = Node(parent)
items[parent] = p_n
else:
p_n = items[parent]
p_n.set_child(c_n)
c_n.set_parent(p_n)
return items
def run_dict_builder():
"""Map the graphs from input and map into a dict.
Sequence:
1- Map all graphs from input trees: list(tuple)
2- For each root node:
2A - Get a root node.
2B - Extract tree under this root from graphs list.
2C - Insert the tree from this root into dict.
3- Return the Dictionary Tree structure.
"""
graphs = build_graphs()
h_table = {}
while len(graphs) > 0:
root = get_a_root(graphs)
extract_tree(graphs, root)
insert_from_root(h_table, root)
return h_table
print(run_dict_builder())
根据您的“示例输出”,3是8的父项。但这不是你的输入所描述的。此外,8不是应该是7岁的孩子吗?我很困惑。
键:value
对有模式吗?3是1、4和5的父项。是的,8岁是7岁的孩子,我解决了这个问题。显然,我还没有生成输出的代码,所以我手工编写了字典。这对字典没有模式。您应该假设父子巢穴的列表可以是任意顺序。您的树不应该是{6:{3:{1:{0:{},4:{},5:{},7:{8:{}}
?您显示3在元组中有children 1、5、4,但输出使1看起来像是有childs 5、4、0。此解决方案工作得非常好。它将我45行不起作用的代码浓缩成一个简单易懂的解决方案。我以前从未见过set()以这种方式使用,在阅读python文档之后,您的用法就不那么明显了。我应该注意,一旦构建了树,它就会保存在缓存中,因此性能不是问题。但是,有数千个父/子关系,并且在添加新数据时需要定期重建树。这可能会作为我正在构建的flask网站的cron运行。你能帮我反向操作吗,即从同一嵌套字典生成父-子对?@user3156040答案可能不适合评论。请你提出一个新问题,然后在这里发布链接,好吗?马特,谢谢你提供了一个非常好的解决方案。这是可行的,但我需要在Python3环境中使用它(应该指定-抱歉!)。如何更改第67行的items.has_键以使其与python 3一起工作<代码>属性错误:“dict”对象没有属性“has_key”@dansafe您可以使用:如果项目中的父项:
<代码>如果输入dict: