簡體   English   中英

在 python 中遞歸構造一個屬樹結構?

[英]Construct a genera- tree structure recursively in python?

我構建了這個節點 class:

 
class Node:
    """
    Node of Tree object:
    """

    def __init__(self, data):
        self.data = data
        self.parent = None
        self.children = list()

    def __repr__(self) -> str:
        return f"Node: {self.data}"

    def set_data(self, data):
        self.data = data

    def get_data(self):
        return self.data

    def set_children(self, *children):
        for child in children:
            child.parent = self
            assert isinstance(child, Node)
            self.children.append(child)

    def get_children(self):
        return self.children

    def set_parent(self, parent):
        assert isinstance(parent, Node)
        parent.set_children(self)

    def get_parent(self):
        return self.parent

    def get_root(self):
        if self.parent == None:
            return self
        p = self.get_parent()
        while bool(p.get_parent()):
            print(bool(p.get_parent()))
            p = p.get_parent()
        return p

    def is_root(self):
        if self.parent is None:
            return True
        return False

    def is_leaf(self):
        if self.children:
            return False
        return True

    def get_level(self):
        if self.is_root():
            return 0
        return 1 + self.parent.get_level()

    def print_tree(self) -> None:
        if self.parent:
            spaces = "|   " * self.get_level()
        prefix = spaces + "|-- " if self.parent else ""
        print(prefix + str(self.data))
        if self.children:
            for child in self.children:
                child.print_tree()

我面臨的問題是,如何創建節點並使用循環為它們分配父母或孩子? 我試過這個:

root = a = Node(0)
for i in range(1, 10):
    new_node = Node(i)
    a.set_children(new_node)
    a = new_node

root.print_tree()

哪個有效,打印:

0
|   |-- 1
|   |   |-- 2
|   |   |   |-- 3
|   |   |   |   |-- 4
|   |   |   |   |   |-- 5
|   |   |   |   |   |   |-- 6
|   |   |   |   |   |   |   |-- 7
|   |   |   |   |   |   |   |   |-- 8
|   |   |   |   |   |   |   |   |   |-- 9

但是,我需要一種使節點可訂閱的方法,如果我需要將更多子節點分配給前一個節點,例如節點 4。我可以將 go 返回給它並分配它們。

也許構建一個單獨的 class,它將索引分配給節點或類似的東西。

我想轉換成樹的數據來自 csv 文件,如下所示:

AUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG02;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;FNS_1700 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_1701 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_3352 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_89069 (TS);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_80304 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_660 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80079 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80412 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_14118 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3008 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3007 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81391 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_17629 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_659 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_665 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81106 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;FNS_80996 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80080 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_4139 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_17634 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_80081 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_2738 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_86546 (RA);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_4704 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_663 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_656 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_17637 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3133 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3000 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_80082 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG01;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;

您可以使用以下 function:

def from_csv(csv):
    parent = root = Node(None) # dummy node
    curdepth = 0
    for line in csv.splitlines():
        depth = len(line) - len(line.lstrip(";"))
        while curdepth > depth:
            parent = parent.parent
            curdepth -= 1
        node = Node(line.strip(";"))
        node.set_parent(parent)
        parent = node
        curdepth += 1
    return root

這是一個演示運行:

csv = """AUG;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG02;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;FNS_1700 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_1701 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_3352 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_89069 (TS);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_80304 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_660 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80079 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80412 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_14118 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3008 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_3007 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81391 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_17629 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_659 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_665 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_81106 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;;FNS_80996 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_80080 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;;FNS_4139 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_17634 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_80081 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_2738 (CD);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_86546 (RA);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_4704 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;FNS_663 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;;;FNS_656 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_17637 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3133 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_3000 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;;;FNS_80082 (FU);;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
;AUG01;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;;
"""

root = from_csv(csv)
root.print_tree()

這輸出:

None
|   |-- AUG
|   |   |-- AUG02
|   |   |   |-- FNS_1700 (CD)
|   |   |   |   |-- FNS_1701 (CD)
|   |   |   |   |   |-- FNS_3352 (FU)
|   |   |   |   |   |-- FNS_89069 (TS)
|   |   |   |   |   |   |-- FNS_80304 (FU)
|   |   |   |   |   |   |-- FNS_660 (FU)
|   |   |   |   |   |   |   |-- FNS_80079 (FU)
|   |   |   |   |   |   |   |-- FNS_80412 (FU)
|   |   |   |   |   |   |-- FNS_14118 (FU)
|   |   |   |   |   |   |-- FNS_3008 (FU)
|   |   |   |   |   |   |-- FNS_3007 (FU)
|   |   |   |   |   |   |   |-- FNS_81391 (FU)
|   |   |   |   |   |   |-- FNS_17629 (FU)
|   |   |   |   |   |-- FNS_659 (FU)
|   |   |   |   |   |   |-- FNS_665 (FU)
|   |   |   |   |   |   |   |-- FNS_81106 (FU)
|   |   |   |   |   |   |   |   |-- FNS_80996 (FU)
|   |   |   |   |   |   |   |-- FNS_80080 (FU)
|   |   |   |   |   |   |   |-- FNS_4139 (FU)
|   |   |   |   |   |-- FNS_17634 (FU)
|   |   |   |   |   |-- FNS_80081 (FU)
|   |   |   |   |-- FNS_2738 (CD)
|   |   |   |   |-- FNS_86546 (RA)
|   |   |   |   |   |-- FNS_4704 (FU)
|   |   |   |   |   |-- FNS_663 (FU)
|   |   |   |   |   |   |-- FNS_656 (FU)
|   |   |   |   |-- FNS_17637 (FU)
|   |   |   |   |-- FNS_3133 (FU)
|   |   |   |   |-- FNS_3000 (FU)
|   |   |   |   |-- FNS_80082 (FU)
|   |   |-- AUG01

這包括一個值為None的根,因為理論上 CSV 格式可能在頂層定義多個節點,因此它代表一個森林 然后虛擬根將這些頂級節點作為其子節點。 如果您希望 CSV 輸入中只有一個頂級節點,請執行以下操作:

root = from_csv(csv).get_children()[0]
root.parent = None
root.print_tree()

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM