Python 将元组列表排序为树结构的递归
Python recursion to sort list of tuples into tree structure
我是编码新手,在尝试对元组列表进行递归排序时遇到了困难。这是我的代码:
# table consists on [(code, parent), (code, parent), ...]
table = [('1', ''),
('1.1', '1'),
('2', ''),
('2.1','2'),
('2.1.1','2.1'),
('3',''),
('3.1','3'),
('4',''),
('4.1','4'),
('4.1.1','4.1'),
('4.1.2','4.1')]
content = {}
def rec(table, parent=None):
while True:
try:
_code = table[0][0]
_parent = table [0][1]
if _parent == '':
content[_code] = _parent
return rec(table[1:])
else:
if _parent in content:
if content[_parent] == '':
content[_parent] = table[0]
else:
content[_parent] = content[_parent], table[0]
return rec(table[1:], parent=_parent)
else:
content[_parent] = table[0]
return rec(table[1:], parent=_parent)
except IndexError:
break
return content
print(rec(table))
我得到的输出:
{'1': ('1.1', '1'), '2': ('2.1', '2'), '2.1': ('2.1.1', '2.1'), '3':('3.1', '3'), '4': ('4.1', '4'), '4.1': (('4.1.1', '4.1'), ('4.1.2','4.1'))}
但所需的输出将是:
{'1': ('1.1', '1'), '2': ('2.1', '2'), {'2.1': ('2.1.1', '2.1')}, '3': ('3.1','3'), '4': ('4.1', '4'), {'4.1': ('4.1.1', '4.1'), ('4.1.2', '4.1')}
我需要这样的东西:
{'node_id': '1', 'name':'somename', 'children': [{'node_id': '1.1' ,'name':'somename', 'children': [{'node_id': '1.1.1', 'name':'somename', 'children': [{'node_id': '1.1.1.1', 'name':'somename', 'children': []}]}, {'node_id': '1.1.2', 'name':'somename', 'children': []}, {'node_id': '1.1.3', 'name':'somename', 'children': []}]}, {'node_id': '1.2', 'name':'somename', 'children': []}]}
关于如何实现我的目标有什么想法吗?
你可以使用递归:
table = [('1', ''), ('1.1', '1'), ('2', ''), ('2.1', '2'), ('2.1.1', '2.1'), ('3', ''), ('3.1', '3'), ('4', ''), ('4.1', '4'), ('4.1.1', '4.1'), ('4.1.2', '4.1')]
def to_dict(d):
return {'node_id':d, 'children':[*map(to_dict, [a for a, b in table if b == d])]}
result = [to_dict(a) for a, b in table if not b]
输出:
[{'node_id': '1', 'children': [{'node_id': '1.1', 'children': []}]}, {'node_id': '2', 'children': [{'node_id': '2.1', 'children': [{'node_id': '2.1.1', 'children': []}]}]}, {'node_id': '3', 'children': [{'node_id': '3.1', 'children': []}]}, {'node_id': '4', 'children': [{'node_id': '4.1', 'children': [{'node_id': '4.1.1', 'children': []}, {'node_id': '4.1.2', 'children': []}]}]}]
编辑:假设您在 table
中的元组有附加信息:
table = [('1', '', 'someval0'), ('1.1', '1', 'someval1'), ('2', '', 'someval2'), ('2.1', '2', 'someval3'), ('2.1.1', '2.1', 'someval4'), ('3', '', 'someval5'), ('3.1', '3', 'someval6'), ('4', '', 'someval7'), ('4.1', '4', 'someval8'), ('4.1.1', '4.1', 'someval9'), ('4.1.2', '4.1', 'someval10')]
def to_dict(d):
return {**(dict(zip(['node_id', 'name'], d))), 'children':[*map(to_dict, [(a, *c) for a, b, *c in table if b == d[0]])]}
result = [to_dict((a, *c)) for a, b, *c in table if not b]
输出:
[{'node_id': '1', 'name': 'someval0', 'children': [{'node_id': '1.1', 'name': 'someval1', 'children': []}]}, {'node_id': '2', 'name': 'someval2', 'children': [{'node_id': '2.1', 'name': 'someval3', 'children': [{'node_id': '2.1.1', 'name': 'someval4', 'children': []}]}]}, {'node_id': '3', 'name': 'someval5', 'children': [{'node_id': '3.1', 'name': 'someval6', 'children': []}]}, {'node_id': '4', 'name': 'someval7', 'children': [{'node_id': '4.1', 'name': 'someval8', 'children': [{'node_id': '4.1.1', 'name': 'someval9', 'children': []}, {'node_id': '4.1.2', 'name': 'someval10', 'children': []}]}]}]
为了使您的输出成为嵌套字典树,它需要有一个规则结构,其中每个节点都是一个字典,其值表示 children 的字典,一直到叶节点他们 children.
的空字典
这是一个构建树的简单循环:
table = [('1', ''),
('1.1', '1'),
('2', ''),
('2.1','2'),
('2.1.1','2.1'),
('3',''),
('3.1','3'),
('4',''),
('4.1','4'),
('4.1.1','4.1'),
('4.1.2','4.1')]
tree = { node:dict() for link in table for node in link }
for child,parent in table:
tree[parent].update({child:tree[child]})
输出:
print(tree[""]) # "" is te root
{
'1': { '1.1': {}},
'2': {
'2.1': { '2.1.1': {}}
},
'3': { '3.1': {}},
'4': {
'4.1': {
'4.1.1': {},
'4.1.2': {}
}
}
}
作为附带好处,此结构为您提供了树中所有节点的索引
使用属性字典(其中之一是children的列表),可以使用相同的方法:
tree = { node:{"id":node,"children":[]} for link in table for node in link }
for child,parent in table:
tree[parent]["children"].append(tree[child])
输出:
print(tree[""]["children"]) # children of root
[ { 'id': '1',
'children': [ { 'id': '1.1', 'children': []} ]
},
{ 'id': '2',
'children': [
{ 'id': '2.1',
'children': [ {'id': '2.1.1', 'children': []} ]
}
]
},
{ 'id': '3',
'children': [ { 'id': '3.1','children': []} ]
},
{ 'id': '4',
'children': [
{ 'id': '4.1',
'children': [
{ 'id': '4.1.1', 'children': []},
{ 'id': '4.1.2', 'children': []}
]
}
]
}
]
递归方法很好,但执行速度会慢得多,并且不会生成索引以通过节点的 ID 访问节点:
def tree(links,node=""):
return {"id":node, "children":[tree(links,child) for child,parent in links if parent==node] }
root = tree(table)
我是编码新手,在尝试对元组列表进行递归排序时遇到了困难。这是我的代码:
# table consists on [(code, parent), (code, parent), ...]
table = [('1', ''),
('1.1', '1'),
('2', ''),
('2.1','2'),
('2.1.1','2.1'),
('3',''),
('3.1','3'),
('4',''),
('4.1','4'),
('4.1.1','4.1'),
('4.1.2','4.1')]
content = {}
def rec(table, parent=None):
while True:
try:
_code = table[0][0]
_parent = table [0][1]
if _parent == '':
content[_code] = _parent
return rec(table[1:])
else:
if _parent in content:
if content[_parent] == '':
content[_parent] = table[0]
else:
content[_parent] = content[_parent], table[0]
return rec(table[1:], parent=_parent)
else:
content[_parent] = table[0]
return rec(table[1:], parent=_parent)
except IndexError:
break
return content
print(rec(table))
我得到的输出:
{'1': ('1.1', '1'), '2': ('2.1', '2'), '2.1': ('2.1.1', '2.1'), '3':('3.1', '3'), '4': ('4.1', '4'), '4.1': (('4.1.1', '4.1'), ('4.1.2','4.1'))}
但所需的输出将是:
{'1': ('1.1', '1'), '2': ('2.1', '2'), {'2.1': ('2.1.1', '2.1')}, '3': ('3.1','3'), '4': ('4.1', '4'), {'4.1': ('4.1.1', '4.1'), ('4.1.2', '4.1')}
我需要这样的东西:
{'node_id': '1', 'name':'somename', 'children': [{'node_id': '1.1' ,'name':'somename', 'children': [{'node_id': '1.1.1', 'name':'somename', 'children': [{'node_id': '1.1.1.1', 'name':'somename', 'children': []}]}, {'node_id': '1.1.2', 'name':'somename', 'children': []}, {'node_id': '1.1.3', 'name':'somename', 'children': []}]}, {'node_id': '1.2', 'name':'somename', 'children': []}]}
关于如何实现我的目标有什么想法吗?
你可以使用递归:
table = [('1', ''), ('1.1', '1'), ('2', ''), ('2.1', '2'), ('2.1.1', '2.1'), ('3', ''), ('3.1', '3'), ('4', ''), ('4.1', '4'), ('4.1.1', '4.1'), ('4.1.2', '4.1')]
def to_dict(d):
return {'node_id':d, 'children':[*map(to_dict, [a for a, b in table if b == d])]}
result = [to_dict(a) for a, b in table if not b]
输出:
[{'node_id': '1', 'children': [{'node_id': '1.1', 'children': []}]}, {'node_id': '2', 'children': [{'node_id': '2.1', 'children': [{'node_id': '2.1.1', 'children': []}]}]}, {'node_id': '3', 'children': [{'node_id': '3.1', 'children': []}]}, {'node_id': '4', 'children': [{'node_id': '4.1', 'children': [{'node_id': '4.1.1', 'children': []}, {'node_id': '4.1.2', 'children': []}]}]}]
编辑:假设您在 table
中的元组有附加信息:
table = [('1', '', 'someval0'), ('1.1', '1', 'someval1'), ('2', '', 'someval2'), ('2.1', '2', 'someval3'), ('2.1.1', '2.1', 'someval4'), ('3', '', 'someval5'), ('3.1', '3', 'someval6'), ('4', '', 'someval7'), ('4.1', '4', 'someval8'), ('4.1.1', '4.1', 'someval9'), ('4.1.2', '4.1', 'someval10')]
def to_dict(d):
return {**(dict(zip(['node_id', 'name'], d))), 'children':[*map(to_dict, [(a, *c) for a, b, *c in table if b == d[0]])]}
result = [to_dict((a, *c)) for a, b, *c in table if not b]
输出:
[{'node_id': '1', 'name': 'someval0', 'children': [{'node_id': '1.1', 'name': 'someval1', 'children': []}]}, {'node_id': '2', 'name': 'someval2', 'children': [{'node_id': '2.1', 'name': 'someval3', 'children': [{'node_id': '2.1.1', 'name': 'someval4', 'children': []}]}]}, {'node_id': '3', 'name': 'someval5', 'children': [{'node_id': '3.1', 'name': 'someval6', 'children': []}]}, {'node_id': '4', 'name': 'someval7', 'children': [{'node_id': '4.1', 'name': 'someval8', 'children': [{'node_id': '4.1.1', 'name': 'someval9', 'children': []}, {'node_id': '4.1.2', 'name': 'someval10', 'children': []}]}]}]
为了使您的输出成为嵌套字典树,它需要有一个规则结构,其中每个节点都是一个字典,其值表示 children 的字典,一直到叶节点他们 children.
的空字典这是一个构建树的简单循环:
table = [('1', ''),
('1.1', '1'),
('2', ''),
('2.1','2'),
('2.1.1','2.1'),
('3',''),
('3.1','3'),
('4',''),
('4.1','4'),
('4.1.1','4.1'),
('4.1.2','4.1')]
tree = { node:dict() for link in table for node in link }
for child,parent in table:
tree[parent].update({child:tree[child]})
输出:
print(tree[""]) # "" is te root
{
'1': { '1.1': {}},
'2': {
'2.1': { '2.1.1': {}}
},
'3': { '3.1': {}},
'4': {
'4.1': {
'4.1.1': {},
'4.1.2': {}
}
}
}
作为附带好处,此结构为您提供了树中所有节点的索引
使用属性字典(其中之一是children的列表),可以使用相同的方法:
tree = { node:{"id":node,"children":[]} for link in table for node in link }
for child,parent in table:
tree[parent]["children"].append(tree[child])
输出:
print(tree[""]["children"]) # children of root
[ { 'id': '1',
'children': [ { 'id': '1.1', 'children': []} ]
},
{ 'id': '2',
'children': [
{ 'id': '2.1',
'children': [ {'id': '2.1.1', 'children': []} ]
}
]
},
{ 'id': '3',
'children': [ { 'id': '3.1','children': []} ]
},
{ 'id': '4',
'children': [
{ 'id': '4.1',
'children': [
{ 'id': '4.1.1', 'children': []},
{ 'id': '4.1.2', 'children': []}
]
}
]
}
]
递归方法很好,但执行速度会慢得多,并且不会生成索引以通过节点的 ID 访问节点:
def tree(links,node=""):
return {"id":node, "children":[tree(links,child) for child,parent in links if parent==node] }
root = tree(table)