简体   繁体   English

如何将给定的列表列表转换为 Python 中的树结构?

[英]How can I convert a given list of lists to a tree structure in Python?

So I'm basically stuck at this problem.所以我基本上被困在这个问题上。 The problem gives us a parts inventory list where each component is made up of other components (in a tree relational manner).该问题为我们提供了一个零件库存清单,其中每个组件都由其他组件组成(以树关系的方式)。 For example the input list can be given as例如,输入列表可以给出为

[["A",[2,"B"],[1,"C"]],
["B",[1,"D"],[1,"E"]],
["D",20.],
["E",10.]
["C",40.]]

, where A is made up of 2 Bs and 1 C, similarly B is made up of 1 D and 1 E. The lists with a float as the last index simply indicate the unit price of the given basic part. ,其中 A 由 2 个 B 和 1 个 C 组成,同样 B 由 1 个 D 和 1 个 E 组成。最后一个索引为浮点数的列表仅表示给定基本部分的单价。

The problem is, I need to convert this structure to a tree representation which can be written as;问题是,我需要将此结构转换为可以写为的树表示;

[1,"A",[2,"B",[1,"D",20.],[1,"E",10.]], [1,"C",40.]]

where we simply bury the children of each node as a list in a nested list structure.我们只是将每个节点的子节点作为一个列表埋在嵌套列表结构中。 In order to achieve this, I tried a recursive-iterative algorithm but as we don't know how many children a node has or what the depth of the tree is, I wasn't able to do so.为了实现这一点,我尝试了一种递归迭代算法,但由于我们不知道一个节点有多少个子节点或树的深度是多少,所以我无法这样做。

Can you recommend me a solution for this problem, thanks in advance.你能推荐我一个解决这个问题的方法吗,在此先感谢。

PS: There is not a predefined order for the input list, its elements can be placed from bottom to top of the tree or shuffled. PS:输入列表没有预定义的顺序,它的元素可以从树的底部到顶部放置或打乱。

If your input structure remains same then you can try something like如果您的输入结构保持不变,那么您可以尝试类似

e = [["A",[2,"B"],[1,"C"]],
["B",[1,"D"],[1,"E"]],
["D",20.],
["E",10.],
["C",40.]]

record = {}

for i in reversed(e):
    if(len(i) == 2):
        record[i[0]] = i[1]
    else:
        # there is children
        temp = []
        for j in i[1:]:
            if(isinstance(record[j[1]], list)):
                temp.append([*j, *record[j[1]]])
            else:
                temp.append([*j, record[j[1]]])
        record[i[0]] = temp

root = e[0][0]
print([1, root, *record[root]])  

output output

[1, 'A', [2, 'B', [1, 'D', 20.0], [1, 'E', 10.0]], [1, 'C', 40.0]]

Otherwise, you can create a Tree structure and get the output.否则,您可以创建树结构并获取 output。

You can leverage the fact that lists are pointers to perform the linking in one pass by copying the children list references within the parent lists:您可以利用列表是指针这一事实,通过在父列表中复制子列表引用来一次性执行链接:

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)

output: output:

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]]

Changing the order of the data does not change the result改变数据的顺序不会改变结果

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]]

Note that, if your data has multiple root items, the function will output them all.请注意,如果您的数据有多个根项,则 function 将 output 全部。 In this instance there is only one so it printed only one root在这种情况下,只有一个,所以它只打印一个根

without dictionaries没有字典

If you are not allowed to use dictionaries, you can still use this approach but you'll have to do a sequential search through the data to find products by their id:如果您不允许使用字典,您仍然可以使用这种方法,但您必须对数据进行顺序搜索以通过其 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

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM