Home > Enterprise >  Python output a list in hierarchy
Python output a list in hierarchy

Time:12-28

I've been trying to write a recursive function for the below code example but the issue im facing is that my loop gets double up in value the next time I run it.


def get_choices():
    choices = []
    nodes = Node.query.filter_by(parent_id=None).all()
    for node in nodes:
        choices.append((node.id, f"{node.value}"))
        if node.children:
            for child in node.children:
                choices.append((child.id, f"-{child.value}"))
                if child.children:
                    for c in child.children:
                        choices.append((c.id, f"--{c.value}"))

    return choices

the code im currently working on


def get_choices():
    c = Node.query.filter_by(parent_id=None).all()

    return _get_choices(c)

def _get_choices(children, depth=0, prev_choices=[]):

    new_choices = prev_choices
    for child in children:
        new_choices.append((child.id, f"{depth * '-'}{child.value}"))
        if child.children:
            _get_choices(child.children, depth 1, new_choices)
    
    return new_choices

CodePudding user response:

I think you were going for something like:

def _get_choices(nodes, depth=0):
    if not nodes:
        return []
    for node in nodes:
        yield (node.id, f"{depth * '-'}{node.value}")
        yield from _get_choices(node.children, depth 1)


def get_choices():
    return list(_get_choices(Node.query.filter_by(parent_id=None).all()))

I don't know what to expect in Node exactly, but if my understanding of your data structure is correct, this will yield a tuple for each node and each of its children, all the way down, depth first.

By the way: it's generally not a good idea to use the name of built-in functions or keywords as variable or attribute names. It works just fine, but you probably want to rename id (which is a built-in function).

Since I didn't have data to test, here's an example that does the same with sample data:

class Node:
    def __init__(self, ident, value, children=None):
        self.ident = ident
        self.value = value
        self.children = children if children else []


data = [
    Node(1, 'a', [Node(2, 'b'), Node(3, 'c', [Node(4, 'd')])]),
    Node(5, 'e', [Node(6, 'f'), Node(7, 'g'), Node(8, 'h')]),
    Node(9, 'i')
]


def _get_choices(nodes, depth=0):
    if not nodes:
        return []
    for node in nodes:
        yield (node.ident, f"{depth * '-'}{node.value}")
        yield from _get_choices(node.children, depth 1)


def get_choices():
    return list(_get_choices(data))


print(result := get_choices())
for __, x in result:
    print(x)

Result:

[(1, 'a'), (2, '-b'), (3, '-c'), (4, '--d'), (5, 'e'), (6, '-f'), (7, '-g'), (8, '-h'), (9, 'i')]
a
-b
-c
--d
e
-f
-g
-h
i
  • Related