从Python中的父/子列表构建树

从Python中的父/子列表构建树,python,algorithm,tree,Python,Algorithm,Tree,使用Python,我有一个字典对象列表,其中包含彼此之间的父/子关系,我希望将其构建到树中。例如: {'UI': 'T071', 'NAME': 'Entity', 'PARENT': None, 'CHILDREN': 'Conceptual Entity'} {'UI': 'T077', 'NAME': 'Conceptual Entity', 'PARENT': 'Entitity', 'CHILDREN': 'Organism Attribute, Finding, Idea or Co

使用Python,我有一个字典对象列表,其中包含彼此之间的父/子关系,我希望将其构建到树中。例如:

{'UI': 'T071', 'NAME': 'Entity', 'PARENT': None, 'CHILDREN': 'Conceptual Entity'}
{'UI': 'T077', 'NAME': 'Conceptual Entity', 'PARENT': 'Entitity', 'CHILDREN': 'Organism Attribute, Finding, Idea or Concept'}
{'UI': 'T032', 'NAME': 'Organism Attribute', 'PARENT': 'Conceptual Entity', 'CHILDREN': 'Clinical Attribute'}
etc.
数据集中共有4个根节点(“父”设置为“无”),它们构成4个独立的树。所以,我打算列一张树的清单

数据不一定以任何形式排序(因此层次结构中较高的节点不一定在列表中较高)。此外,id(UI)没有特定顺序(T071在树中不一定比T072高)。它们的名称是唯一的,数据集使用它们的名称而不是id(UI)来显示关系

我有一个简单的课程:

class node():
    def __init__(self, value):
        self.value = value
        self.children = []

    def add_child(self, obj):
        self.children.append(obj)

我有点困惑于如何处理这个问题。非常感谢您的建议。

我认为最好是两次通过。首先,创建一个将名称链接到节点的字典。然后您可以有效地添加您的项目

我的代码:

nodes = dict((e["NAME"], node(e)) for e in l)
for e in l:
    if e["PARENT"] is not None:
        nodes[e["PARENT"]].add_children(nodes[e["NAME"])
如果需要根,可以使用上面的If,也可以过滤节点

roots = [n for n in nodes.values() if d.value["PARENT"] is None]

我曾经用一个dict表示了一个*ix进程树,每个父进程的子进程pid列表。所以你得到:

dict_[1] = [2, 3, 4]
dict_[2] = [5, 100]
dict_[3] = [6, 200]
dict_[4] = [7, 300]
dict_[6] = [400]
它似乎工作得很好

可以选择是否希望叶节点与空列表一起存在,或者只是不显示在树中。我已经在上面展示了它们,它们没有出现在dict级别的树中


我认为这仅适用于pid(节点)只能出现在树中的一个位置的情况。例如,100不能是2岁和4岁的孩子。

该代码最多可穿透字典树5级。当到达某个对象时,它会检查该对象是否为numpy。如果是,则打印其形状。如果不是,则写入对象的类型。通过选择“级别”,可以确定树的深度。当前的实现可以深入到5个级别

def tree_view_dict(d, level=999):
    for key in d.keys():
        print('|')
        print(key, end = '')
        if isinstance(d[key], dict) and level > 1:
            print()
            for key2 in d[key].keys():
                print('|__', key2, end = '')
                if isinstance(d[key][key2], dict) and level > 2:
                    print()
                    for key3 in d[key][key2]:
                        print('   |__', key3, end = '')
                        if isinstance(d[key][key2][key3], dict) and level > 3:
                            print()
                            for key4 in d[key][key2][key3]:
                                print('     |__', key4, end = '')
                                if isinstance(d[key][key2][key3][key4], dict) and level > 4:
                                    print()
                                    for key5 in d[key][key2][key3][key4]:
                                        print('       |__', key5, end = '')
                                else:
                                    print(': ', d[key][key2][key3][key4].shape if type(d[key][key2][key3][key4]).__module__ == 'numpy' else type(d[key][key2][key3][key4]))
                        else:
                            print(': ', d[key][key2][key3].shape if type(d[key][key2][key3]).__module__ == 'numpy' else type(d[key][key2][key3]))
                else:
                    print(': ', d[key][key2].shape if type(d[key][key2]).__module__ == 'numpy' else type(d[key][key2]))
        else:
            print(': ', d[key].shape if type(d[key]).__module__ == 'numpy' else type(d[key]))
    pass

d={'UI':'T032','NAME':'organic Attribute','PARENT':'Conceptual Entity','CHILDREN':{'CHILDREN_array':np.array([[1,2],[3,4]]),'CHILDREN_NAME':'NAME'}
树状视图(d,级别=5)
结果是


|
UI:  <class 'str'>
|
NAME:  <class 'str'>
|
PARENT:  <class 'str'>
|
CHILDREN
|__ CHILDREN_array:  (2, 2)
|__ CHILDREN_name:  <class 'str'>```

|
用户界面:
|
姓名:
|
起源:
|
儿童
|__子数组:(2,2)
|__儿童姓名:```

XD是否有意使用双关语?顺便说一句,
dicts
dict
是存储图形信息的一种非常自然的方式。无需创建单独的节点对象来存放数据。请不要发布仅包含代码的答案。解释代码正在做什么以及它如何解决问题。此外,反复嵌套几乎相同的代码通常是需要重构的标志。肯普,谢谢你的投入。代码渗透到字典树中多达5个级别。当到达某个对象时,它会检查该对象是否为numpy。如果是,则打印其形状。如果不是,则写入对象的类型。通过选择“级别”,可以确定树的深度。当前的实现可以深入到5个级别。我同意你们所说的,最好是重构一些看起来更好的东西,并深入到字典中去。