将节点树转换为字典

时间:2019-11-10 14:59:02

标签: python python-3.x

下面是具有编程语言的树结构(使用节点实例构建)的节点类定义。现在如何使用节点类方法将分层节点数据树结构转换为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字典

  

{“书籍”:{          “网络”:{            “前端”:{              “ html”:[“缺少的手册”,“核心html5画布”],              “ css”:[“ css袖珍参考”,“ css深度”],              “ js”:[“您不知道js”,“精通JavaScript”]            },            “后端”:{              “ php”:[“现代php”],              “ python”:[“深入python”,“适合所有人的python”,              “思考Python”]            }          },          “数据库”:{            “ 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)

2 个答案:

答案 0 :(得分:1)

您有一个更大的问题,因为您使用的是同一类来表示书籍类别和实际书籍。鉴于此,不可能以编程方式确定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)的结果会==达到您的预期输出。

答案 1 :(得分:0)

简单的递归函数:

def to_dict(node):
  if isinstance(node, nodeData.Node):
     return {node._name:to_dict(node._children)}
  if all(isinstance(i, nodeData.Node) for i in node):
     return (lambda x:x if all(x.values()) else list(x))({i._name:to_dict(i._children) for i in node})
  return node

print(to_dict(rootNode))

输出:

{'books': {'web': {'front-end': {'html': ['the missing manual', 'core html5 canvas'], 'css': ['css pocket reference', 'css in depth'], 'js': ["you don't know js", 'eloquent javascript']}, 'back-end': {'php': ['modern php'], 'python': ['dive into python', 'python for everybody', 'Think Python']}}, 'database': {'sql': ['mysql', 'postgresql'], 'nosql': ['mongodb', 'cassandra']}}}