首页 > 解决方案 > 将节点树转换为字典

问题描述

下面是具有树结构(使用节点实例构建)的编程语言的节点类定义。现在如何使用节点类方法将分层节点数据树结构转换为python字典?在底部查看所需的输出。

class Node(object):
    def __init__(self, name, parent=None):
        self._name = name
        self._children = []
        self._parent = parent

        if parent is not None:
            parent.addChild(self)

    def addChild(self, child):
        self._children.append(child)

    def name(self):
        return self._name

    def setName(self, name):
        self._name = name

    def child(self, row):
        return self._children[row]

    def childCount(self):
        return len(self._children)

    def parent(self):
        return self._parent


rootNode   = nodeData.Node("books")
web_node = nodeData.Node("web", rootNode)
database_node = nodeData.Node("database", rootNode)
front_end_node = nodeData.Node("front-end", web_node)
back_end_node = nodeData.Node("back-end", web_node)
sql_node = nodeData.Node("sql", database_node)
nosql_node = nodeData.Node("nosql", database_node)
html_node = nodeData.Node("html", front_end_node)
css_node = nodeData.Node("css", front_end_node)
js_node = nodeData.Node("js", front_end_node)
php_node = nodeData.Node("php", back_end_node)
python_node = nodeData.Node("python", back_end_node)
mysql_node = nodeData.Node("mysql", sql_node)
postgresql_node = nodeData.Node("postgresql", sql_node)
mongodb_node = nodeData.Node("mongodb", nosql_node)
cassandra_node = nodeData.Node("cassandra", nosql_node)
html_book_one_node = nodeData.Node("the missing manual", html_node)
html_book_two_node = nodeData.Node("core html5 canvas", html_node)
css_book_one_node = nodeData.Node("css pocket reference", css_node)
css_book_two_node = nodeData.Node("css in depth", css_node)
js_book_one_node = nodeData.Node("you don't know js", js_node)
js_book_two_node = nodeData.Node("eloquent javascript", js_node)
php_book_one_node = nodeData.Node("modern php", php_node)
python_book_one_node = nodeData.Node("dive into python", python_node)
python_book_two_node = nodeData.Node("python for everybody", python_node)
python_book_three_node = nodeData.Node("Think Python", python_node)
mongodb_book_one_node = nodeData.Node("mongodb in action", mongodb_node)
mongodb_two_node = nodeData.Node("scaling mongodb", mongodb_node)

输出

从节点树抽象到 python 字典

{"books":{ "web":{ "front-end":{ "html":["the missing manual", "core html5 canvas"], "css":["css pocket reference", "css in depth"], "js":["你不懂 js", "eloquent javascript"] }, "back-end":{ "php":["modern php"], "python":["dive进入 python"、"python 适合所有人"、"Think Python"] } }、"database":{ "sql":{ "mysql":[]、"postgresql":[] }、"nosql":{ "mongodb “:[”mongodb 在行动”,“缩放 mongodb”],“cassandra”:[] }}}}

更新代码

class Node(object):
    def __init__(self, name, parent=None):
        self._name = name
        self._children = []
        self._parent = parent

        if parent is not None:
            parent.addChild(self)

    def addChild(self, child):
        self._children.append(child)

    def name(self):
        return self._name

    def setName(self, name):
        self._name = name

    def child(self, row):
        return self._children[row]

    def childCount(self):
        return len(self._children)

    def parent(self):
        return self._parent

class categoryNode(Node):
    def __init__(self, name, parent=None):
        super(categoryNode, self).__init__(name, parent)

class subCategoryNode(Node):
    def __init__(self, name, parent=None):
        super(subCategoryNode, self).__init__(name, parent)

class languageNode(Node):
    def __init__(self, name, parent=None):
        super(languageNode, self).__init__(name, parent)

class BookNode(Node):
    def __init__(self, name, parent=None):
        super(BookNode, self).__init__(name, parent)


rootNode   = Node("books")
web_node = categoryNode("web", rootNode)
database_node = categoryNode("database", rootNode)
front_end_node = subCategoryNode("front-end", web_node)
back_end_node = subCategoryNode("back-end", web_node)
sql_node = subCategoryNode("sql", database_node)
nosql_node = subCategoryNode("nosql", database_node)
html_node = languageNode("html", front_end_node)
css_node = languageNode("css", front_end_node)
js_node = languageNode("js", front_end_node)
php_node = languageNode("php", back_end_node)
python_node = languageNode("python", back_end_node)
mysql_node = languageNode("mysql", sql_node)
postgresql_node = languageNode("postgresql", sql_node)
mongodb_node = languageNode("mongodb", nosql_node)
cassandra_node = languageNode("cassandra", nosql_node)
html_book_one_node = BookNode("the missing manual", html_node)
html_book_two_node = BookNode("core html5 canvas", html_node)
css_book_one_node = BookNode("css pocket reference", css_node)
css_book_two_node = BookNode("css in depth", css_node)
js_book_one_node = BookNode("you don't know js", js_node)
js_book_two_node = BookNode("eloquent javascript", js_node)
php_book_one_node = BookNode("modern php", php_node)
python_book_one_node = BookNode("dive into python", python_node)
python_book_two_node = BookNode("python for everybody", python_node)
python_book_three_node = BookNode("Think Python", python_node)
mongodb_book_one_node = BookNode("mongodb in action", mongodb_node)
mongodb_two_node = BookNode("scaling mongodb", mongodb_node)

标签: pythonpython-3.x

解决方案


您有一个更大的问题,因为您使用同一个类来表示书籍类别和实际书籍。鉴于此,不可能以编程方式确定它是空类别mysql_nodepostgresql_node不是书籍。

为了使这项工作如您所愿,您需要重新设计数据结构。我建议有一个_children子类别列表和另一个_books书名列表(作为字符串)。请注意,这个数据结构仍然有点模棱两可,因为没有子类别且没有书籍的节点可以呈现为空列表(即没有书籍的终端类别)或空字典(即没有子类别的非终端类别) ; 我从这个问题中推断出一个空列表是期望的结果。

class Node:
    def __init__(self, name, parent=None):
        self._name = name
        self._children = []
        self._parent = parent
        self._books = []

        if parent is not None:
            parent.addChild(self)

    def name(self):
        return self._name

    def setName(self, name):
        self._name = name

    def parent(self):
        return self._parent

    def addChild(self, child):
        if self._books:
            raise ValueError('Node cannot have both sub-categories and books')
        self._children.append(child)

    def child(self, row):
        return self._children[row]

    def childCount(self):
        return len(self._children)

    def addBook(self, book):
        if self._children:
            raise ValueError('Node cannot have both sub-categories and books')
        self._books.append(book)

    def book(self, row):
        return self._books[row]

    def bookCount(self):
        return len(self._books)

rootNode = Node("books")
web_node = Node("web", rootNode)
database_node = Node("database", rootNode)
front_end_node = Node("front-end", web_node)
back_end_node = Node("back-end", web_node)
sql_node = Node("sql", database_node)
nosql_node = Node("nosql", database_node)
html_node = Node("html", front_end_node)
css_node = Node("css", front_end_node)
js_node = Node("js", front_end_node)
php_node = Node("php", back_end_node)
python_node = Node("python", back_end_node)
mysql_node = Node("mysql", sql_node)
postgresql_node = Node("postgresql", sql_node)
mongodb_node = Node("mongodb", nosql_node)
cassandra_node = Node("cassandra", nosql_node)

html_node.addBook("the missing manual")
html_node.addBook("core html5 canvas")
css_node.addBook("css pocket reference")
css_node.addBook("css in depth")
js_node.addBook("you don't know js")
js_node.addBook("eloquent javascript")
php_node.addBook("modern php")
python_node.addBook("dive into python")
python_node.addBook("python for everybody")
python_node.addBook("Think Python")
mongodb_node.addBook("mongodb in action")
mongodb_node.addBook("scaling mongodb")

def node_to_dict(node):
    def helper(n):
        if n.childCount() > 0:
            return { c.name(): helper(c) for c in n._children }
        else:
            return list(n._books)
    return { node.name(): helper(node) }

的结果是否node_to_dict(rootNode)符合==您的预期输出。


推荐阅读