【问题标题】:n-depth tree: set parent value based on children valuesn-depth tree:根据子值设置父值
【发布时间】:2018-08-28 09:42:17
【问题描述】:

n-depth dict 中,值设置在层次结构的最深级别:

{
    "name": "root",
    "value": None, # expected value to be 80
    "children": [
        {
            "name": "a",
            "value": None, # expected value to be 30
            "children": [
                { "name": "a.1", "value": 10 },
                { "name": "a.2", "value": 20 }
            ]
        },
        {
            "name": "b",
            "value": None, # expected value to be 50
            "children": [
                { "name": "b.1", "value": 25 },
                {
                    "name": "b.2",
                    "value": None, # expected value to be 25
                    "children": [
                        {"name": "b.2.1", "value": 5},
                        {"name": "b.2.2", "value": 5},
                        {"name": "b.2.3", "value": 5},
                        {"name": "b.2.4", "value": 5},
                        {"name": "b.2.5", "value": 5}
                    ]
                }
            ]
        }
    ]
}

根据对其子代value(即总和)执行的操作的结果,递归设置每个父代value 的方法是什么?

【问题讨论】:

  • 你尝试过什么吗?它是如何失败的?
  • @mkrieger 我尝试了使用队列和堆栈的反向级别顺序遍历模式,但我不知道如何跟踪每个级别的子级。

标签: python


【解决方案1】:

鉴于您的数据结构和要更新的值列表,您可以在递归中使用next

def update(d, targets):
   return {a:[update(i, targets) for i in b] if isinstance(b, list) else update(b, targets) if isinstance(b, dict) else next(targets) if not b else b for a, b in d.items()}

targets = [80, 30, 50, 25]
results = update(nlist, iter(targets))

输出:

{'children': [{'children': [{'name': 'a.1', 'value': 10},
                        {'name': 'a.2', 'value': 20}],
           'name': 'a',
           'value': 30},
          {'children': [{'name': 'b.1', 'value': 25},
                        {'children': [{'name': 'b.2.1', 'value': 5},
                                      {'name': 'b.2.2', 'value': 5},
                                      {'name': 'b.2.3', 'value': 5},
                                      {'name': 'b.2.4', 'value': 5},
                                      {'name': 'b.2.5', 'value': 5}],
                         'name': 'b.2',
                         'value': 25}],
           'name': 'b',
           'value': 50}],
 'name': 'root',
 'value': 80}

【讨论】:

  • 谢谢!我一直在寻找更灵活的解决方案。检查我的答案。
【解决方案2】:

我终于设法使用迭代的level order traversal pattern (BFS) 做到了,我只是遗漏了几个细节。

这种方法之所以有效,是因为深度迭代顺序是有保证的,所以一旦我们到达一个有子节点的节点,它的所有子级子节点都已经计算完毕。

解决办法:

def reverseTraversal(obj):

    def parentOperation(node):
        out = 0
        for child in node['children']:
            out = out + child['value']
        return out

    if obj is None:
        return
    queue = []
    stack = []
    queue.append(obj)
    while len(queue) > 0:
        temp = queue.pop(0)
        stack.append(temp)
        if 'children' in temp and len(temp['children']) > 0:
            for child in temp['children']:
                queue.append(child)

    while len(stack)>0:
        node = stack.pop()
        if 'children' in node and len(node['children']) > 0:
            node['value'] = parentOperation(node)

# obj is the original dict
obj = reverseTraversal(obj)
print(obj)

结果:

{
  "name": "root",
  "value": 80,
  "children": [
    {
      "name": "a",
      "value": 30,
      "children": [
        {"name": "a.1","value": 10},
        {"name": "a.2","value": 20}
      ]
    },
    {
      "name": "b",
      "value": 50,
      "children": [
        {"name": "b.1","value": 25},
        {
          "name": "b.2",
          "value": 25,
          "children": [
            {"name": "b.2.1","value": 5},
            {"name": "b.2.2","value": 5},
            {"name": "b.2.3","value": 5},
            {"name": "b.2.4","value": 5},
            {"name": "b.2.5","value": 5}
          ]
        }
      ]
    }
  ]
}

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2022-12-10
    • 1970-01-01
    • 2014-09-13
    • 1970-01-01
    • 2020-10-11
    • 1970-01-01
    • 2022-08-03
    • 1970-01-01
    相关资源
    最近更新 更多