Python 输出层级列表

Python output a list in hierarchy

我一直在尝试为下面的代码示例编写一个递归函数,但我面临的问题是我的循环在下次 运行 时价值翻倍。


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

我目前正在处理的代码


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

我想你想要的是:

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

我不知道 Node 中会发生什么,但是如果我对您的数据结构的理解是正确的,那么这将为每个节点及其每个子节点生成一个元组,一直向下, 深度优先.

顺便说一句:使用内置函数或关键字的名称作为变量或属性名称通常不是一个好主意。它工作得很好,但你可能想重命名 id(这是一个内置函数)。

由于我没有要测试的数据,下面是一个对示例数据执行相同操作的示例:

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)

结果:

[(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