简体   繁体   English

从具有级别的列表构造树

[英]Construct a tree from a list with levels

I have some data(Python list of dict s) which looks like: 我有一些数据( dict的Python list ),看起来像:

[
    {'value': 'A', 'level': 0},
    {'value': 'B', 'level': 1},
    {'value': 'C', 'level': 2},
    {'value': 'D', 'level': 1},
    {'value': 'E', 'level': 2},
    {'value': 'F', 'level': 2},
    {'value': 'G', 'level': 0},
    {'value': 'H', 'level': 1},
    ...
]

It represents a tree, which looks like: 它代表一棵树,看起来像:

<root>
|
+---A
|   |
|   +---B
|   |   |
|   |   +---C
|   |
|   +---D
|       |
|       +---E
|       |
|       +---F
+---G
    |
    +---H

And here's what I want : Efficient, elegant(Pythonic?) way to construct a tree from the array which has levels(in other words, depths) only. 就是我想要的 :高效,优雅(Pythonic?)方式从数组中构造一个只有水平(换句话说,深度)的树。

So that I could access to the tree: 这样我就可以访问树了:

root = build_tree(data) # or somewhat proper arguments

print(root.children) # => [<Node A>, <Node G>]
print(root.children[0].children) # => [<Node B>, <Node D>]
print(root.children[0].children[1].children]) # => [<Node E>, <Node F>]
print(root.children[1].children) # => [Node G]
print(root.children[1].children[0].children) # => []

I struggled to make some recursive functions to achieve it, but suddenly my brain stopped working. 我努力做一些递归函数来实现它,但突然我的大脑停止了工作。 I'm waiting for your help. 我在等你的帮忙。

Thank you. 谢谢。

--- EDITED --- ---编辑---

Here's what I wrote: 这是我写的:

class TreeNode(object):
    def __init__(self, parent, value):
        self.parent = parent
        self.children = []

        self.__dict__.update(**value)

    def __repr__(self):
        return '<TreeNode %s>' % self.value

def build_tree(list, parent, start_idx=0, depth=0):
    current = TreeNode(parent, list[start_idx])
    parent.children.append(current)

    for idx in xrange(start_idx + 1, len(list)):
        if list[idx]['level'] == current.level:
            build_tree(list, parent, idx)
        elif list[idx]['level'] == current.level + 1:
            build_tree(list, current, idx)
        elif list[idx]['level'] < current.level:
            break

def print_tree(root, depth=0):
    for child in root.children:
        print('  ' * depth + '%r' % child)
        print_tree(child, depth + 1)

if __name__ == '__main__':
    data = [
        {'value': 'A', 'level': 0},
        {'value': 'B', 'level': 1},
        {'value': 'C', 'level': 2},
        {'value': 'D', 'level': 1},
        {'value': 'E', 'level': 2},
        {'value': 'F', 'level': 2},
        {'value': 'G', 'level': 0},
        {'value': 'H', 'level': 1},
    ]

    root = TreeNode(None, {'value': 'root'})
    build_tree(data, root)

    print_tree(root)

And it gives: 它给出了:

<TreeNode A>
  <TreeNode B>
    <TreeNode C>
    <TreeNode E>
    <TreeNode F>
    <TreeNode F>
  <TreeNode D>
    <TreeNode E>
    <TreeNode F>
    <TreeNode F>
  <TreeNode D>
    <TreeNode E>
    <TreeNode F>
    <TreeNode F>
  <TreeNode H>
<TreeNode G>
  <TreeNode H>

The code should be simple. 代码应该很简单。 Your scheme implies there is an order to the children, so I will use a list . 你的计划意味着孩子们有一个订单,所以我会使用一个list

In [8]: class Node:
   ...:     def __init__(self, val=None):
   ...:         self.value = val
   ...:         self.children = []
   ...:     def __repr__(self):
   ...:         return "<Node {}>".format(self.value)
   ...:

The algorithm is also simple. 算法也很简单。 Start at the root. 从根开始。 Iterate over the data. 迭代数据。 While you are less than "level" nodes deep, continue moving down the children going to the last child appended attempting to go down the last node in children. 虽然您的节点深度低于"level"节点,但继续向下移动子节点,直到最后一个子节点,尝试沿着节点中的最后一个节点向下移动。 If attempting to index into the last child fails, then we know we are where we have to be (assuming the input is well behaved!) and we append a new node with the value "value" . 如果尝试索引到最后一个子节点失败,那么我们知道我们必须在哪里(假设输入表现良好!)并且我们追加一个值为"value"的新节点。 If you don't fail and make it to "level" , append a new node with the value "value" . 如果没有失败并使其达到"level" ,请附加值为"value"的新节点。 Return to the root and repeat while you are not done iterating over the data. 返回根并重复,而不是迭代数据。

In [9]: root = Node()

In [10]: for record in data:
    ...:     last = root
    ...:     for _ in range(record['level']):
    ...:         last = last.children[-1]
    ...:     last.children.append(Node(record['value']))
    ...:

Now, to check out our tree: 现在,看看我们的树:

In [12]: root.children
Out[12]: [<Node A>, <Node G>]

In [13]: root.children[0].children
Out[13]: [<Node B>, <Node D>]

In [14]: root.children[0].children[1].children
Out[14]: [<Node E>, <Node F>]

In [15]: root.children[1].children
Out[15]: [<Node H>]

In [16]: root.children[1].children[0].children
Out[16]: []

Using your handy print_tree function: 使用方便的print_tree函数:

In [24]: def print_tree(root, depth=0):
    ...:     for child in root.children:
    ...:         print('  ' * depth + '%r' % child)
    ...:         print_tree(child, depth + 1)
    ...:

In [25]: print_tree(root)
<Node A>
  <Node B>
    <Node C>
  <Node D>
    <Node E>
    <Node F>
<Node G>
  <Node H>

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

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