从JSON创建层次结构路径

时间:2013-07-22 09:38:20

标签: python 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
        }
    ]
}

5 个答案:

答案 0 :(得分:2)

这是一种方法:

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(这就是你为ids提供的内容)那个例子JSON)。

对于您的示例用法:

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

答案 1 :(得分:0)

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

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

或使用dict comprehensions:

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]

答案 2 :(得分:0)

我相信你想要的东西:

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到树根的路径中名称的串联。

答案 3 :(得分:0)

这可能是你想要的:

>>> 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

答案 4 :(得分:0)

你也可以这样做。但为此你的输入应该是这样的。 将[{1}}替换为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
    }
]