【问题标题】:Recursively printing a family tree with objects递归打印带有对象的家谱
【发布时间】:2018-11-27 17:53:56
【问题描述】:

我需要有关递归表示家谱的帮助。这是数据:

children_and_parents = {
    "Mary": ["Patricia", "Lisa"], 
    "Patricia": ["Barbara", "Helen", "Maria"], 
    "Maria": ["Keren", "Carol"], 
    "Barbara": ["Betty"]
}

我需要提到值是对象,所以我需要调用它们children_and_parents["Maria"].child 来获取['Patricia', 'Lisa']

我目前拥有的递归程序:

def draw_family_tree(person, level=0):
    if person in children_and_parents:
        for i in range (len(children_and_parents[person].child)):
            print (" "*level, person)
            return draw_family_tree(children_and_parents[person].child[i], level+3) 

它目前正在做的是:

Mary
   Patricia
      Barbara

但结果应该是这样的:

Mary
   Patricia
       Barbara
           Betty
       Helen
       Maria
           Keren
           Carol
   Lisa

我卡在程序的开头。如果有人愿意提供帮助,我将不胜感激。

粗略代码:https://repl.it/repls/BlondCavernousExponents

【问题讨论】:

    标签: python python-3.x object recursion family-tree


    【解决方案1】:

    找到树的根是单独操作的一个很好的候选。在您的示例中,我们知道它是"Mary",因此我们可以相应地进行迭代。如果不知道,您可以编写一个函数来返回不是任何其他节点的子节点的第一个父节点:

    def find_root(tree):
        all_children = {x for y in tree.values() for x in y}
        
        for node in tree:
            if node not in all_children:
                return node
    

    对于实际的打印过程,在遍历子节点之前尝试打印父节点。我还建议将树作为参数传递给函数以维护封装并使其可重用(即不依赖于调用范围中存在的名为 children_and_parents 的变量)。

    def draw_family_tree(tree, root, gap=3, level=0):
        if root:
            print(" " * level + root)
    
            if root in tree:
                for child in tree[root]:
                    draw_family_tree(tree, child, gap, level + gap)
    

    我们还可以避免draw_family_tree 中的副作用并让它返回一个生成器,让调用者决定如何处理结果:

    def find_root(tree):
        all_children = {x for y in tree.values() for x in y}
        
        for node in tree:
            if node not in all_children:
                return node
    
    def draw_family_tree(tree, root, gap=3, level=0):
        if root:
            yield " " * level + root
    
            if root in tree:
                for child in tree[root]:
                    yield from draw_family_tree(tree, child, gap, level + gap)
    
    if __name__ == "__main__":
        children_and_parents = {
            "Mary": ["Patricia", "Lisa"], 
            "Patricia": ["Barbara", "Helen", "Maria"], 
            "Maria": ["Keren", "Carol"], 
            "Barbara": ["Betty"]
        }
        root = find_root(children_and_parents)
    
        for node in draw_family_tree(children_and_parents, root):
            print(node)
    

    输出:

    Mary
       Patricia
          Barbara
             Betty
          Helen
          Maria
             Keren
             Carol
       Lisa
    

    正如前面讨论中提到的,我不建议将类用于简单的<string, list> 对;它增加了很多没有功能的冗长,实际上有点误导,因为parent 暗示这个人有一个父母(它实际上是指对象所代表的人的名字)。如果您确实选择走这条路,则需要将.child 附加到所有括号访问并为您的班级编写__repr__(self) 函数(或print(root.parent)

    【讨论】:

    • 它得到我的错误消息只能将 str (不是“dict”)连接到 str ,正如我提到的值,孩子是一个对象,因为我在他们需要的程序的其他部分使用它们这样做可能是个问题
    • 您没有发布该代码,因此您需要发布它或为您的班级编写str() 方法。否则,我只能猜测类定义是什么。但是,打印逻辑是相同的,所以通过不发布它,我假设您能够推断出您的需求。
    • 一会儿我会为你发布它
    • 应该有附件,我查过了
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-12-10
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多