Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Convert node tree to dictionary

Below is the node class definition with tree structure (built using node instance) of programming languages. Now how to convert hierarchical node data tree structure to python dictionary using node class method ? See desired output at bottom.

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)

Output

From node tree abstraction to python dictionary

{"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":["mongodb in action", "scaling mongodb"], "cassandra":[] }}}}

Updated Code

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)
like image 280
Ruchit Avatar asked Mar 18 '26 10:03

Ruchit


1 Answers

You have a bigger problem, because you're using the same class to represent both book categories and actual books. Given this, it is impossible to programmatically determine that mysql_node and postgresql_node are empty categories rather than books.

To make this work how you want, you will need to redesign the data structure. I suggest having a list _children for subcategories and another list _books for book titles (as strings). Note that this data structure is still a little ambiguous because a node with no subcategories and no books could be rendered as an empty list (i.e. a terminal category with no books) or an empty dictionary (i.e. a non-terminal category with no subcategories); I infer from the question that an empty list is the desired result.

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) }

The result of node_to_dict(rootNode) does == your expected output.

like image 151
kaya3 Avatar answered Mar 20 '26 00:03

kaya3



Donate For Us

If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!