【问题标题】:Given a flat list of (parent,child), create a hierarchical dictionary tree [closed]给定(父,子)的平面列表,创建一个分层字典树[关闭]
【发布时间】:2017-08-02 12:16:07
【问题描述】:

我有一个包含名称的元组列表。这些名字是父名和子名,我想用他们的名字创建一个分层字典树。 例如,我有以下列表:

[('john','marry'),('mike','john'),('mike','hellen'),('john','elisa')]

我想创建这个:

{
    'mike':{
        'john':{
            'marry':{}
            'elisa':{}
         }
         'hellen':{}
        }
}

【问题讨论】:

  • 如果有一个额外的元素会发生什么,比如('elisa', 'mike')
  • 到目前为止您尝试过什么?你具体卡在哪里了?
  • 我认为这是错误的,因为 mike 是 john 和 Hellen 的父亲,而 john 是 Elisa 的父亲,这意味着 Elisa 是 mike 的孙子孙女,不可能是 mike 的母亲。
  • ('elisa', 'mike') 如果 elisa childname 是 mike (newbirth) 是可能的
  • 我在求职面试中反对这个练习,但我无法解决它。练习与我发布的完全一样;我唯一能想到的就是找到祖父的名字,在这种情况下是迈克;在那之后,我想不出有什么东西可以比较其余的名字。

标签: python python-3.x dictionary


【解决方案1】:

假设它表现良好(没有循环、没有重复名称或一个孩子有多个父母),您可以简单地使用“有向图”并遍历它。为了找到根,我还使用了一个包含布尔值的字典,该值指示该名称是否有任何父级:

lst = [('john','marry'), ('mike','john'), ('mike','hellen'), ('john','elisa')]

# Build a directed graph and a list of all names that have no parent
graph = {name: set() for tup in lst for name in tup}
has_parent = {name: False for tup in lst for name in tup}
for parent, child in lst:
    graph[parent].add(child)
    has_parent[child] = True

# All names that have absolutely no parent:
roots = [name for name, parents in has_parent.items() if not parents]

# traversal of the graph (doesn't care about duplicates and cycles)
def traverse(hierarchy, graph, names):
    for name in names:
        hierarchy[name] = traverse({}, graph, graph[name])
    return hierarchy

traverse({}, graph, roots)
# {'mike': {'hellen': {}, 'john': {'elisa': {}, 'marry': {}}}}

【讨论】:

    【解决方案2】:

    无论如何都可以选择:

    data = [('john','marry'),('mike','john'),('mike','hellen'),('john','elisa')]
    
    roots = set()
    mapping = {}
    for parent,child in data:
        childitem = mapping.get(child,None)
        if childitem is None:
            childitem =  {}
            mapping[child] = childitem
        else:
            roots.discard(child)
        parentitem = mapping.get(parent,None)
        if parentitem is None:
            mapping[parent] = {child:childitem}
            roots.add(parent)
        else:
            parentitem[child] = childitem
    
    tree = {id : mapping[id] for id in roots}
    
    print (tree)
    

    结果:

    {'mike': 
            {
             'hellen': {}, 
             'john': {
                      'elisa': {}, 
                      'marry': {}}}}
    

    感谢@WillemVanOnsem Recursively creating a tree hierarchy without using class/object

    【讨论】:

    • .mapping dict 正在自动更新,你能告诉它是如何完成的示例:data=[['B', 'A'],['C', 'B']] 第一次迭代: mapping={'B': {}, 'A': {'B': {}}} 第二次迭代: parentitem={} 在执行最后一行代码后,我希望 parentitem 只更改 parentitem={'C ': {}} 即使最后一行代码没有手动更新映射字典,wiered 的行为也会自动更改,这是如何工作的?映射字典是如何自动更改的?映射={'B': {'C': {}}, 'A': {'B': {'C': {}}}, 'C': {}}
    【解决方案3】:
    def get_children(parent, relations):
        children = (r[1] for r in relations if r[0] == parent)
        return {c: get_children(c, relations) for c in children}
    
    the_list = [('john','marry'),('mike','john'),('mike','hellen'),('john','elisa')]
    
    parents, children = map(set, zip(*the_list))
    the_tree = {p: get_children(p, the_list) for p in (parents - children)}
    
    print(the_tree)
    

    【讨论】:

      猜你喜欢
      • 2019-01-05
      • 1970-01-01
      • 2023-03-25
      • 1970-01-01
      • 2013-09-04
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2020-07-06
      相关资源
      最近更新 更多