2013-07-22 218 views
1

鑑於下面的JSON,爲給定的「id」創建「name」層次結構列表的最佳方式是什麼?層次結構中可以有任意數量的部分。從JSON創建層次結構路徑

例如,提供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 
     } 
    ] 
} 

回答

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(這就是你在那個JSON例子中獲得的id)。

爲了您的使用例子:

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

完美。我將'path.append(section [「name」])''改爲'path.insert(0,section [「name」])',以便列表反轉。謝謝。 – user489176

0

可能最簡單的方法是創建一個將ID映射到名稱的字典。例如:

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

或使用字典內涵:

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] 
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返回的名稱的串聯路徑中的至樹的根。

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 
0

你也可以做這樣的。但爲此,你的意見應該是這樣的。 在您的輸入字典中用Nonetrue替換nullTrue

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