【问题标题】:How can I convert a given list of lists to a tree structure in Python?如何将给定的列表列表转换为 Python 中的树结构?
【发布时间】:2021-05-05 23:50:04
【问题描述】:

所以我基本上被困在这个问题上。该问题为我们提供了一个零件库存清单,其中每个组件都由其他组件组成(以树关系的方式)。例如,输入列表可以给出为

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

,其中 A 由 2 个 B 和 1 个 C 组成,同样 B 由 1 个 D 和 1 个 E 组成。以浮点数作为最后一个索引的列表仅表示给定基本部分的单价。

问题是,我需要将此结构转换为可以写成的树表示;

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

我们只是将每个节点的子节点作为一个列表埋在嵌套列表结构中。为了实现这一点,我尝试了一种递归迭代算法,但由于我们不知道一个节点有多少个子节点或树的深度是多少,所以我无法这样做。

你能推荐我解决这个问题的方法吗,在此先感谢。

P.S:输入列表没有预定义的顺序,它的元素可以从树的底部到顶部放置或打乱。

【问题讨论】:

    标签: python loops recursion tree iteration


    【解决方案1】:

    如果您的输入结构保持不变,那么您可以尝试类似

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

    输出

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

    否则,您可以创建一个树结构并获取输出。

    【讨论】:

    • 非常感谢先生,我还有最后一个问题。如果我们要实现一个没有字典的解决方案,这可能吗?再次感谢您的宝贵时间。
    • 是的,创建一个具有self.childrenself.count 属性的Node 类。叶子的会有一个价格。然后你递归地做 BFS 来创建数组。
    【解决方案2】:

    您可以利用列表是指针这一事实,通过在父列表中复制子列表引用来一次性执行链接:

    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
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2019-04-23
      相关资源
      最近更新 更多