从JSON创建层次结构路径



给定下面的JSON,为给定的"id"创建"name"的分层列表的最佳方法是什么?层次结构中可以有任意数量的节。

例如,提供id"156"将返回"添加存储设备,引导配置,配置"

我一直在考虑使用iteritems(),但需要一些帮助。

 {
    "result": true,
    "sections": [
        {
            "depth": 0,
            "display_order": 1,
            "id": 154,
            "name": "Configuration",
            "parent_id": null,
            "suite_id": 5
        },
        {
            "depth": 1,
            "display_order": 2,
            "id": 155,
            "name": "Guided Configuration",
            "parent_id": 154,
            "suite_id": 5
        },
        {
            "depth": 2,
            "display_order": 3,
            "id": 156,
            "name": "Add Storage Devices",
            "parent_id": 155,
            "suite_id": 5
        },
        {
            "depth": 0,
            "display_order": 4,
            "id": 160,
            "name": "NEW",
            "parent_id": null,
            "suite_id": 5
        },
        {
            "depth": 1,
            "display_order": 5,
            "id": 161,
            "name": "NEWS",
            "parent_id": 160,
            "suite_id": 5
        }
    ]
}

这里有一种方法:

def get_path(data, section_id):
    path = []
    while section_id is not None:
        section = next(s for s in data["sections"] if s["id"] == section_id)
        path.append(section["name"])
        section_id = section["parent_id"]
    return ", ".join(path)

它假设datajson.loads(json_text)或类似的结果,而section_idint(这就是您在该示例JSON中获得的ID)。

对于您的示例用法:

>>> get_path(data, 156)
u'Add Storage Devices, Guided Configuration, Configuration'

可能最简单的方法是创建一个将ID映射到名称的字典。例如:

name_by_id = {}
data = json.loads(the_json_string)
for section in data['sections']:
    name_by_id[section['id']] = section['name']

或使用dict理解:

name_by_id = {section['id']: section['name'] for section in data['sections']}

然后你可以得到特定的元素:

>>> name_by_id[156]
... 'Add Storage Devices'

或获取所有ID:

>>> name_by_id.keys()
... [160, 161, 154, 155, 156]

这可能就是您想要的:

>>> sections = data['sections']
>>> lookup = {section['id']: section for section in sections}
>>> lookup[None] = {}
>>> for section in sections:
        parent = lookup[section['parent_id']]
        if 'childs' not in parent:
            parent['childs'] = []
        parent['childs'].append(section)
>>> def printRecurse (section, indent = 0):
        if 'childs' in section:
            section['childs'].sort(lambda x: x['display_order'])
            for child in section['childs']:
                print('{}{}: {}'.format('  ' * indent, child['id'], child['name']))
                printRecurse(child, indent + 1)
>>> printRecurse(lookup[None])
154: Configuration
  155: Guided Configuration
    156: Add Storage Devices
160: NEW
  161: NEWS

我相信你想要这样的东西:

def get_name_for_id(id_num, sections):
    cur_depth = -1
    texts = []
    for elem in sections:
        if elem['depth'] < cur_depth:
            del texts[:]
        elif elem['depth'] == cur_depth:
            texts.pop()
        texts.append(elem['name'])
        cur_depth = elem['depth']
        if elem['id'] == id_num:
            return ', '.join(reversed(texts))

使用您的数据返回:

In [11]: get_name_for_id(156, data['sections'])
Out[11]: 'Add Storage Devices, Guided Configuration, Configuration'

此外,它还考虑了基于depth的层次结构,因此,如果在您的数据中id 156指的是depth = 0,则结果为:

In [16]: get_name_for_id(156, data['sections'])
Out[16]: 'Add Storage Devices'

如果id 156的深度为1,则返回的值为:

In [22]: get_name_for_id(156, data['sections'])
Out[22]: 'Add Storage Devices, Configuration'

基本上它考虑了树:

深度156=0深度156=1深度156=2

 154  156          154                 154
  |                 |                   |
  |                /                  155
 155             155 156                |
                                       156

并且它返回从156到树的根的路径中的名称的串联。

您也可以这样做。但为此,您的输入应该是这样的。将输入字典中的null替换为None,将true替换为True

def filtering(d,id_n):
    names = []        
    while id_n:
        id_n,name=[(sec['parent_id'],sec['name']) for sec in d['sections'] if sec['id'] == id_n][0]
        names.append(name)
    return names
d = {
"result": True,    #making 'true' with 'True'
"sections": [
    {
        "depth": 0,
        "display_order": 1,
        "id": 154,
        "name": "Configuration",
        "parent_id": None,
        "suite_id": 5
    },
    {
        "depth": 1,
        "display_order": 2,
        "id": 155,
        "name": "Guided Configuration",
        "parent_id": 154,
        "suite_id": 5
    },
    {
        "depth": 2,
        "display_order": 3,
        "id": 156,
        "name": "Add Storage Devices",
        "parent_id": 155,
        "suite_id": 5
    },
    {
        "depth": 0,
        "display_order": 4,
        "id": 160,
        "name": "NEW",
        "parent_id": None,
        "suite_id": 5
    },
    {
        "depth": 1,
        "display_order": 5,
        "id": 161,
        "name": "NEWS",
        "parent_id": 160,
        "suite_id": 5
    }
]

}

用给定的输入测试代码:-

id_n = 156
>>> filtering(d,id_n)
['Add Storage Devices', 'Guided Configuration', 'Configuration']

最新更新