【问题标题】:Python family tree from dict with defined parents [closed]来自dict的Python家谱与定义的父母[关闭]
【发布时间】:2013-11-11 09:00:03
【问题描述】:

从如下所示的字典中创建家谱的最快方法是什么:

family = [
    {'name': 'a', 'parent': ''},
    {'name': 'b', 'parent': 'a'},
    {'name': 'c', 'parent': 'a'},
    {'name': 'd', 'parent': 'b'},
    {'name': 'e', 'parent': 'd'},
    {'name': 'f', 'parent': ''},
    {'name': 'g', 'parent': 'f'},
    {'name': 'h', 'parent': 'a'}
]

最终,我正在尝试将其打印出来(带有大量额外信息,但这是一般的想法),如下所示的列表:

a
  b
    d
      e
  c
  h
f
  g

解决方案是创建一个函数来循环列表直到它为空,在它找到父项的每个项目上使用 .pop() 吗?还是在python中有更好的方法?

这是一个更大问题的一部分,但是,我正在努力寻找解决这个小部分的最佳方法。因此,即使是 lambda 的噩梦也可能是可能的。请尝试以易于扩展的简洁方式回答:)

【问题讨论】:

  • -1。好的,所以您没有尝试任何方法,只是希望我们为您编写代码。本网站用于学习,而非将工作外包给志愿者。
  • 我尝试使用 while 循环和 pop() 在每个项目上执行此操作,同时我试图找到它的位置。然后将该项目放入更大的字典中以跟踪树。但是,感觉这不是最好的解决方案,因为我必须多次查看列表。我没有任何代码,因为我没有完成它,主要是因为我想问是否有更好的,甚至是内置的方式来做到这一点。
  • 父母可以拥有多少孩子,这棵树的深度也没有限制。

标签: python family-tree


【解决方案1】:

我建议将您的 dicts 列表处理成更有用的数据结构。我会制作一个从父母到他们的孩子列表的字典映射(没有父母的“祖先”将被包括为空字符串的“孩子”)。

然后,递归应用以下算法打印出树,从祖先列表和depth0开始:

  1. 遍历输入列表中的人员(如果列表为空,则不执行任何操作,作为我们的基本案例)。
  2. 对于每个人,首先打印他们的姓名,前面加上depth 空格。
  3. 从我们的字典中查找该人的孩子的列表,然后递归,depth 大一。
  4. 继续看下一个人。

代码如下:

from collections import defaultdict

def preprocess(family_list):
    descent_dict = defaultdict(list)
    for person in family_list:
        descent_dict[person["parent"]].append(person["name"])
    return descent_dict

def print_family_tree(descent_dict, people, depth=0):
    for person in people:
        print("  "*depth+person)
        print_family_tree(descent_dict, descent_dict[person], depth+1)

示例运行:

>>> family = [
    {'name': 'a', 'parent': ''},
    {'name': 'b', 'parent': 'a'},
    {'name': 'c', 'parent': 'a'},
    {'name': 'd', 'parent': 'b'},
    {'name': 'e', 'parent': 'd'},
    {'name': 'f', 'parent': ''},
    {'name': 'g', 'parent': 'f'},
    {'name': 'h', 'parent': 'a'}
]

>>> d = preprocess(family)
>>> print_family_tree(d, d[''])
a
  b
    d
      e
  c
  h
f
  g

【讨论】:

    【解决方案2】:

    警告 - 这是一个糟糕的解决方案

    请改用@Blckknght 提供的以下答案。这是一个糟糕的解决方案,运行时间为 O(N**2),因为它依赖于格式错误的数据结构。

    您需要使用一个递归函数,该函数接收一个根节点,打印该节点的所有子节点,然后调用自身。像下面这样的东西。不要试图在适当的位置编辑家庭字典,你只会让你的生活变得比它需要的更难。

    类似下面的函数可能对你有用。请记住,这只是一个简单的示例,您需要添加相当多的错误处理,以避免它在您有循环或 owt 时崩溃。

    INDENT = ' ' #Change this to taste
    
    def print_family(parent,family,indent=0):
        for child in family:
            if child['parent'] == parent:
    
                 # Print here
                 print '%s%s' % (INDENT * indent,child['name'])
    
                 # Call on the child
                 print_family(child['name'],family,indent + 1)
    
    # Kick it off with the root node
    print_family('',family)
    

    【讨论】:

    • 这正是我要找的,谢谢!!我想我把我遇到的问题复杂化了,这既简单又完美。
    • 这段代码是不必要的浪费,主要是因为它依赖于作为输入提供的相当无用的字典列表,而不是构建更强大的数据结构。打印结果需要O(N**2) 时间,而在O(N) 时间很容易做到。
    • 好点@Blckknght。我应该注意到(我应该在工作时快速输入 SO 答案所得到的)我已经编辑了我的答案。
    猜你喜欢
    • 1970-01-01
    • 2018-07-31
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2022-06-13
    相关资源
    最近更新 更多