1

鉴于下面的 JSON,为给定的“id”创建“名称”分层列表的最佳方法是什么?层次结构中可以有任意数量的部分。

例如,提供 id "156" 将返回 "Add Storage Devices, Guided Configuration, Configuration"

我一直在研究使用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
        }
    ]
}
4

5 回答 5

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_id是一个int(这是您在该示例 JSON 中为 ids 所拥有的)。

对于您的示例用法:

>>> get_path(data, 156)
u'Add Storage Devices, Guided Configuration, Configuration'
于 2013-07-22T10:12:58.930 回答
0

可能最简单的方法是创建一个将 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]
于 2013-07-22T09:56:46.267 回答
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,因此如果在您的数据中id156 指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 到树根的路径中名称的串联。

于 2013-07-22T09:58:20.167 回答
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
于 2013-07-22T10:11:11.723 回答
0

你也可以这样做。但是为此,您的输入应该是这样的。在您的输入字典中替换为nullNonetrueTrue

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']
于 2013-07-22T11:26:58.313 回答