【问题标题】:Recursively creating a tree hierarchy without using class/object在不使用类/对象的情况下递归创建树层次结构
【发布时间】:2017-07-24 02:56:12
【问题描述】:

我在 Python 3 中创建树层次结构时遇到问题。我希望能够在不使用类的情况下做到这一点。

我需要开始的数据不按顺序和格式['ID','Parent']

data=[['E1', 'C1'],['C1', 'P1'],['P1', 'R1'],['E2', 'C2'],['C2', 'P2'],['P2', 'R1'],['C3', 'P2'],['E3', 'C4'],['C4', 'P3'],
  ['P3', 'R2'],['C5', 'P3'],['E4', 'C6'],['C6', 'P4'], ['P4', 'R2'],['E5', 'C7'],['C7', 'P5'],['P5', 'R3'],['E6', 'C9'],['C9', 'P6'],['P6', 'R3'],
  ['C8', 'P6'],['E7', 'C10'],['C10', 'P7'],['P7', 'R4'],['C11', 'P7'],['E8', 'C12'],['C12', 'P8'],['P8', 'R4']]

我想在不使用类的情况下创建(树)字典变量,最终得到如下结果:

Tree={'R1':{'P1':{},'P2':{}},'R2':{}} etc

Tree={'R1':[{'P1':[],'P2':[]}],'R2':[]} etc

显然 R1 和 R2 有更多的孩子,但也许这就是 Tree 结构的样子?

【问题讨论】:

  • 是否知道数据中元素出现的顺序?
  • 你知道你不能对dict中的不同元素使用相同的键,对吧? ;)
  • Python 字典必须有唯一的键。如果您尝试定义{'ID': 1, 'ID': 2} 之类的内容,您最终会得到{'ID': 2},因为第二个'ID' 将覆盖第一个。
  • 不确定你有什么反对类,因为这就是 dict 是什么——创建一个 dict 子类相当容易,这将使你想做的事情变得非常容易。见What is the best way to implement nested dictionaries?
  • 我已经编辑了问题以提供一些示例数据,这不是为了开始

标签: python python-3.x recursion tree hierarchy


【解决方案1】:

您可以简单地遍历每个 child,parent 元组,创建将子项和父项的 id 映射到包含这些元素的子项的列表的字典。我们会一直这样做,直到完成。

roots = set()
mapping = {}
for child,parent 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

现在我们已经这样做了,roots 是一组树根的 id:所以对于每个这样的元素,我们知道没有任何 id 是父元素。对于roots 中的每个id,我们可以简单地从mapping 中获取,这是结构{'childid':child} 的字典,其中childid 是id(这里是string),child 又是一个这种形式的字典。

所以你可以像这样打印它们:

for root in roots:
    print(mapping[root])

所以在你的情况下,tree 是:

tree = { id : mapping[id] for id in roots }

对于您的示例data,它会生成:

>>> tree
{'R1': {'P1': {'C1': {'E1': {}}}, 'P2': {'C2': {'E2': {}}, 'C3': {}}}, 'R2': {'P4': {'C6': {'E4': {}}}, 'P3': {'C5': {}, 'C4': {'E3': {}}}}, 'R3': {'P6': {'C8': {}, 'C9': {'E6': {}}}, 'P5': {'C7': {'E5': {}}}}, 'R4': {'P8': {'C12': {'E8': {}}}, 'P7': {'C11': {}, 'C10': {'E7': {}}}}}

【讨论】:

  • 感谢您的输入,但输出树似乎不完整,例如 P4 应该有子 C6 并且缺少诸如 C9 之类的 ID,实际上很多都缺少
  • @new_to_coding:你是对的。我发现了这个错误。现在它应该可以工作了。
  • 这是正确的,非常感谢您的帮助!
  • @WillemVanOnsem .mapping 字典正在自动更新,你能说出它是如何完成样本的吗:data=[['B', 'A'],['C', 'B']] 1st迭代:mapping={'B': {}, 'A': {'B': {}}} 第二次迭代:parentitem={} 在最后一行代码执行后,我期望 parentitem 只改变 parentitem={ 'C': {}} 即使最后一行代码没有手动更新映射字典,wiered 的行为也自动更改了映射字典这是如何工作的?映射字典是如何自动更改的?映射={'B': {'C': {}}, 'A': {'B': {'C': {}}}, 'C': {}}
  • @star:你在roots中查找根父母,所以最后roots只包含A。另一个不会自动更新,它们只是对 same 字典的两个引用,因此如果我们更新该字典,我们会在使用该字典的所有位置看到此更新。
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 2019-12-18
  • 2017-04-18
  • 2023-03-24
  • 2012-12-14
  • 1970-01-01
  • 2013-02-22
  • 2018-02-21
相关资源
最近更新 更多