从dict的Python家谱与定义的父母

时间:2013-11-11 09:00:03

标签: python family-tree

从字典中创建家族树的最快方法是什么:

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的噩梦也许是可能的。请尝试以一种易于扩展的简洁方式回答:)

2 个答案:

答案 0 :(得分:3)

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

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

  1. 对输入列表中的人进行迭代(如果列表为空,则不执行任何操作,作为我们的基本情况)。
  2. 对于每个人,首先打印其名称前面有depth个空格。
  3. 从我们的字典中查找该人的孩子的名单,并递归,depth更大。
  4. 继续下一个人。
  5. 以下是代码:

    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
    

答案 1 :(得分:1)

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

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

您将需要使用一个递归函数,该函数接收根节点,打印该节点的所有子节点,然后调用自身。像下面这样的东西。不要试图编辑家庭词典,你只会让你的生活更加艰难。

以下功能可能对您有用。请记住,这只是一个简单的例子,你需要添加一些错误处理,以避免在你有一个周期或欠款时它会爆炸。

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)