在Python中展平嵌套的JSON层次结构

时间:2018-06-20 15:24:05

标签: python json jupyter-notebook nested-loops hierarchy

我将以我绝对不是开发人员的身份开头,但是我被丢了这份工作,我只是迷路了。这是我第一次使用python,也是7年来的第一次编码,而且进展不太顺利。

我拥有的JSON是一个组织树,其中每个级别都可能在其下面有子级。

我需要在Jupyter Notebook中用Python编写脚本以将其展平为这种格式,或者类似的方式,其中每个新子代都是新行。

change.after

这是JSON:

public override static var activityCategory: UIActivityCategory {
    return .share;
}

我已经尝试了各种for循环,并且已经搜寻了几天互联网,但是我认为我缺少一些非常基础的知识来完成这项工作。我会非常感激某人可以提供的任何帮助。

这是我的首发:

 level1 | level2 | level3
 org1
 org1      org2
 org1      org2    org3

[{
    "Id": "f035de7f",
    "Name": "Org1",
    "ParentId": null,
    "Children": [{
        "Id": "8c18a70d",
        "Name": "Org2",
        "ParentId": "f035de7f",
        "Children": []
    }, {
        "Id": "b4514099",
        "Name": "Org3",
        "ParentId": "f035de7f",
        "Children": [{
            "Id": "8abe58d1",
            "Name": "Org4",
            "Children": []
        }]
    }, {
        "Id": "8e35bdc3",
        "Name": "Org5",
        "ParentId": "f035de7f",
        "Children": [{
            "Id": "331fffbf",
            "Name": "Org6",
            "ParentId": "8e35bdc3",
            "Children": [{
                "Id": "3bc3e085",
                "Name": "Org7",
                "ParentId": "331fffbf",
                "Children": []
            }]
        }]
    }]
}]

3 个答案:

答案 0 :(得分:0)

您可以使用堆栈处理嵌套结构:

  • 从最外面的列表 reversed 开始,作为堆栈,每个列表都有一个空的元组,以跟踪组织路径
  • s'last_value循环中,从堆栈中取出顶部元素。在该组织中进行您需要做的事情,例如记录名称。在组织路径中产生一行,并添加当前组织名称。
  • '0' -> '1' 'L' -> '1' '0' -> 'H' 'L' -> 'H' 键中的所有元素以及上级组织的组织路径添加到堆栈中。
  • 循环直到堆栈完成。

需要逆转,因为从堆栈中获取元素会以相反的顺序进行。您仍然想为该作业使用堆栈(而不是队列),因为我们要深度优先地输出信息。

这看起来像这样:

while stack:

然后您可以遍历上面的函数以获取所有路径:

Children

答案 1 :(得分:0)

您可以递归地迭代数据。前缀表示到目前为止看到的名称列表,数据表示您仍然必须学习的词典列表。

data = [{
    "Id": "f035de7f",
    "Name": "Org1",
    "ParentId": None,
    "Children": [{
        "Id": "8c18a70d",
        "Name": "Org2",
        "ParentId": "f035de7f",
        "Children": []
    }, {
        "Id": "b4514099",
        "Name": "Org3",
        "ParentId": "f035de7f",
        "Children": [{
            "Id": "8abe58d1",
            "Name": "Org4",
            "Children": []
        }],
    }, {
        "Id": "8e35bdc3",
        "Name": "Org5",
        "ParentId": "f035de7f",
        "Children": [{
            "Id": "331fffbf",
            "Name": "Org6",
            "ParentId": "8e35bdc3",
            "Children": [{
                "Id": "3bc3e085",
                "Name": "Org7",
                "ParentId": "331fffbf",
                "Children": []
            }],
        }],
    }],
}]



def flatten(data, prefix):
    if not data:
        return [prefix]

    result = []
    for org in data:
        name = org["Name"]
        result.extend(flatten(org["Children"], prefix + [name]))
    return result

print(flatten(data, []))
# [['Org1', 'Org2'], ['Org1', 'Org3', 'Org4'], ['Org1', 'Org5', 'Org6', 'Org7']]

相同,使用yield:

def flatten(data, prefix):
    if not data:
        yield prefix

    for org in data:
        name = org["Name"]
        yield from flatten(org["Children"], prefix + [name])

print(list(flatten(data, [])))

如果需要所有部分列表,则解决方案较短:

def flatten(data, prefix):
    yield prefix

    for org in data:
        name = org["Name"]
        yield from flatten(org["Children"], prefix + [name])

print(list(flatten(data, [])))
# [[], ['Org1'], ['Org1', 'Org2'], ['Org1', 'Org3'], ['Org1', 'Org3', 'Org4'], ['Org1', 'Org5'], ['Org1', 'Org5', 'Org6'], ['Org1', 'Org5', 'Org6', 'Org7']]

答案 2 :(得分:0)

json递归树可以具有多个根,并且叶子不必强制指定void子代。例如,这是一棵树,具有两个根“ a”和“ b”,并且节点仅具有“层”数据,该数据是节点深度(“子级”是可选的):

json_struct = [
    {
    'level': 'a0',
    'children': [{'level': 'a0.1',  'children':
                    [{'level': 'a0.1.1', 'children': []}]},
                 {'level': 'a0.2',  'children': [
                     {'level': 'a0.2.1', 'children': [
                            {'level': 'a0.2.1.1'},
                            {'level': 'a0.2.1.2'},
                            {'level': 'a0.2.1.3'},
                            {'level': 'a0.2.1.4', 'children': [{'level': 'a0.2.1.4.1'}, {'level': 'a0.2.1.4.2'}]}
                            ]
                        }
                    ]
                  },
                 {'level': 'a0.3', 'children': []},
                 {'level': 'a0.4', 'children': [{'level': 'a0.4.1'}, {'level': 'a0.4.2', 'children': []}]}
                ]
    },
    {
        'level': 'b0',
        'children': [{'level': 'b0.1', 'children': [{'level': 'b0.1.1'}]},
                     {'level': 'b0.2', 'children': [{'level': 'b0.2.1', 'children': [
                         {'level': 'b0.2.1.1'},
                         {'level': 'b0.2.1.2'},
                         {'level': 'b0.2.1.3', 'children': [{'level': 'b0.2.1.3.1'}, {'level': 'b0.2.1.3.2'}]},
                         {'level': 'b0.2.1.4'}
                            ]
                        }]},
                     {'level': 'b0.3'}
                     ]
    }
]

代码必须返回叶子并完成分支路径,直到每次离开:

def flatten_json_tree(nodes, lower_nodes_key='children', path=[]):
    if not nodes:       # void node
        yield path    # so it is a leaf

    for node in nodes:  # go on into each branch of the tree
        level = node['level']   # get node datas
        try:
            lower_nodes = node[lower_nodes_key]     # search for lower nodes
        except KeyError:
            lower_nodes = []    # no lower nodes

        yield from flatten_json_tree(lower_nodes, lower_nodes_key, path + [level])     # continue to explore the branch until leaf

if __name__ == "__main__":
    for path in list(flatten_json_tree(json_struct)):
        leaf = path[-1:][0]
        complete_path = ''
        for node in path:
            complete_path += node + (' -> ' if node is not leaf else '')
        print("LEAF: {:20s} PATH: {}".format(leaf, complete_path))

它显示:

  1. 叶:a0.1.1路径:a0-> a0.1-> a0.1.1
  2. 叶:a0.2.1.1路径:a0-> a0.2-> a0.2.1-> a0.2.1.1
  3. 叶:a0.2.1.2路径:a0-> a0.2-> a0.2.1-> a0.2.1.2
  4. 叶:a0.2.1.3路径:a0-> a0.2-> a0.2.1-> a0.2.1.3
  5. 叶:a0.2.1.4.1路径:a0-> a0.2-> a0.2.1-> a0.2.1.4-> a0.2.1.4.1
  6. 叶:a0.2.1.4.2路径:a0-> a0.2-> a0.2.1-> a0.2.1.4-> a0.2.1.4.2
  7. 叶:a0.3路径:a0-> a0.3
  8. 叶:a0.4.1路径:a0-> a0.4-> a0.4.1
  9. 叶:a0.4.2路径:a0-> a0.4-> a0.4.2
  10. 叶:b0.1.1路径:b0-> b0.1-> b0.1.1
  11. 叶:b0.2.1.1路径:b0-> b0.2-> b0.2.1-> b0.2.1.1
  12. 叶:b0.2.1.2路径:b0-> b0.2-> b0.2.1-> b0.2.1.2
  13. 叶:b0.2.1.3.1路径:b0-> b0.2-> b0.2.1-> b0.2.1.3-> b0.2.1.3.1
  14. 叶:b0.2.1.3.2路径:b0-> b0.2-> b0.2.1-> b0.2.1.3-> b0.2.1.3.2
  15. 叶:b0.2.1.4路径:b0-> b0.2-> b0.2.1-> b0.2.1.4
  16. 叶:b0.3路径:b0-> b0.3