Galmi
Galmi

Reputation: 763

Nested list to string

I have a list of instances of class Test. This class have method like name and parent

[Test('a', ''), Test('b', ''), Test('c', 'a'), Test('d', 'a'), Test('e', 'c')]

First argument is name, second parent. Parent arg is simply a arg name of parent class. I want convert this list to string like:

Test('a', '')
  |-- Test('c', 'a')
        |-- Test('e', 'c')
  |-- Test('d', 'a')
Test('b', '')

I looking for the most CPU-effective way to convert this list to string. Items in list can be nested at multiples (10,100, 1000, ..) levels, and I don't care about memory used.

Upvotes: 0

Views: 557

Answers (3)

Rusty Rob
Rusty Rob

Reputation: 17173

If you end up using DFS as fiver suggested you could use networkx

import networkx as nx
stuff=[('a', ''), ('b', ''), ('c', 'a'), ('d', 'a'), ('e', 'c')]
G=nx.DiGraph()
for i in stuff:
    G.add_edge(i[1],i[0])
print G.adj

Then it is a mater of iterating it with DFS

Upvotes: 0

Petar Ivanov
Petar Ivanov

Reputation: 93020

Here is code that works as is. Basically convert the array into a tree and then use recursive DFS to print it (you can use iterative DFS if you want):

class Test:
    def __init__(self, name, parent):
        self.name = name
        self.parent = parent
    def __repr__(self):
        return "Test('"+self.name+"', '"+self.parent+"')"



li = [Test('a', ''), Test('b', ''), Test('c', 'a'), Test('d', 'a'), Test('e', 'c')]

dict = {"":(None,[])} #name to (node,children)
#add nodes
for item in li:
    dict[item.name] = (item, [])
#add children
for item in li:
    dict[item.parent][1].append(dict[item.name])

def printTree(dict, name, indent):
    newIndent=indent
    if name!="":
        print(indent + str(dict[name][0]))
        if indent == "": newIndent="  |-- "
        else: newIndent = "      "+indent
    for child in dict[name][1]:
        printTree(dict, child[0].name, newIndent) 


printTree(dict, "", "")

Upvotes: 2

JBernardo
JBernardo

Reputation: 33397

You should use another container, like that:

class Test:
    def __init__(self, name, sub=None):
        self.name = name
        self.sub = sub if sub is not None else []

elements = [Test('a', [Test('c', [Test('e')]), Test('d')]), Test('b')]

then just iterate elements to print:

def show(x, indent=0):
    for i in x:
        print('\t'*indent + 'Test(%r)' % i.name)
        show(i.sub, indent+1)

show(elements)

should print:

Test('a')
    Test('c')
        Test('e')
    Test('d')
Test('b')

You may change the indentation to anything you prefer (I'm using tabs).

Upvotes: 0

Related Questions