您可以利用列表是指针这一事实,通过在父列表中复制子列表引用来一次性执行链接:
def buildTree(data):
index = { c[0]:c for c in data } # used to access components by their id
root = index.copy() # used to retain top level component(s)
for component in data:
if isinstance(component[1],float): continue # no linking on leaf items
for i,(_,prod) in enumerate(component[1:],1): # expand children
component[i][1:] = index[prod] # embed child in parent
root.pop(prod) # remove child from root
return [[1,*rv] for rv in root.values()] # output root item(s)
输出:
data = [["A",[2,"B"],[1,"C"]],
["B",[1,"D"],[1,"E"]],
["D",20.0],
["E",10.0],
["C",40.0]]
print(*buildTree(data))
# [1, 'A', [2, 'B', [1, 'D', 20.0], [1, 'E', 10.0]], [1, 'C', 40.0]]
改变数据的顺序并不会改变结果
data = [["D",20.0],
["E",10.0],
["B",[1,"D"],[1,"E"]],
["C",40.0],
["A",[2,"B"],[1,"C"]]]
print(*buildTree(data))
# [1, 'A', [2, 'B', [1, 'D', 20.0], [1, 'E', 10.0]], [1, 'C', 40.0]]
请注意,如果您的数据有多个根项,则该函数将全部输出。在这种情况下,只有一个,所以它只打印一个根
没有字典
如果您不允许使用字典,您仍然可以使用这种方法,但您必须对数据进行顺序搜索才能通过其 id 查找产品:
def buildTree(data):
roots = data.copy() # used to retain top level component(s)
for component in data:
if isinstance(component[1],float): continue # no linking on leaf items
for i,(_,prod) in enumerate(component[1:],1): # expand children
child = next(c for c in data if c[0]==prod) # find child with id
component[i][1:] = child # embed child in parent
roots.remove(child) # remove child from root
return [[1,*rv] for rv in roots] # output root items