2012-08-13 149 views
2

我有一个像一本字典:遍历嵌套字典并获取Python中的路径?

{ 
    "checksum": "b884cbfb1a6697fa9b9eea9cb2054183", 
    "roots": { 
     "bookmark_bar": { 
     "children": [ { 
      "date_added": "12989159740428363", 
      "id": "4", 
      "name": "test2", 
      "type": "url", 
      "url": "chrome://bookmarks/#1" 
     } ], 
     "date_added": "12989159700896551", 
     "date_modified": "12989159740428363", 
     "id": "1", 
     "name": "bookmark_bar", 
     "type": "folder" 
     }, 
     "other": { 
     "children": [ { 
      "date_added": "12989159740428363", 
      "id": "4", 
      "name": "test", 
      "type": "url", 
      "url": "chrome://bookmarks/#1" 
     } ], 
     "date_added": "12989159700896557", 
     "date_modified": "0", 
     "id": "2", 
     "name": "aaa", 
     "type": "folder" 
     }, 
     "synced": { 
     "children": [ ], 
     "date_added": "12989159700896558", 
     "date_modified": "0", 
     "id": "3", 
     "name": "bbb", 
     "type": "folder" 
     } 
    }, 
    "version": 1 
} 

一切都开始于“根”,他们有两种类型的数据:URL和文件夹,它们是字典。 如果它是一个文件夹,它必须具有'children'键,该键的值是一个列表,我们可以在其中放置更多的URL和文件夹。

现在我想遍历这个嵌套的字典,以获得在所有子文件夹中的网址,所以我写了一个函数:

def traverse(dic): 
    for i in dic: 
     if i['type'] == 'folder': 
      for j in traverse(i['children']): 
       yield j 
     elif i['type'] == 'url': 
      yield i 

,我可以用它这样的:

traverse(dictionary['roots']['bookmark_bar']['children']) 

它完美的作品。但它只是生成一个URL的字典,我不知道它在哪里。 我也想得到路径。我该怎么做?

+4

请问请使用标识格式化字典吗?你能否从中删除所有不需要理解你的问题的东西? – 2012-08-13 07:35:31

+0

该字典现在可读。 – 2012-08-13 07:45:45

+1

什么是您的预期输出 – Rakesh 2012-08-13 08:28:33

回答

1

不舒尔如果我得到你想要的东西,但你可能想这样做:

def traverse(dic, path=None): 
    if not path: 
     path = [] 
    for i in dic: 
     local_path = path[:].append(i) 
     if i['type'] == 'folder': 
      for j in traverse(i['children'], local_path): 
       yield j, local_path 
     elif i['type'] == 'url': 
      yield i, local_path 

现在你的函数产生的项目和按键的顺序,以获得该项目在某个位置。

+0

我正在考虑这些方面。这仍然需要工作,因为当我不是字典时(这通常是:-)),它会在'i ['type']'处受到'TypeError'的攻击 – azhrei 2012-08-14 00:54:36

+0

太好了。这并不完美,但给我一个想法。谢谢! – 2012-08-14 14:34:01

4

我和你有一个稍微不同的用例:我需要将表示客户端设置的变量深度JSON结构扁平化为用于存储在数据库中的键值对。我不能让jsbueno的回答工作,因为我还需要一些能够处理的情况下,没有孩子是明确列出或包含的,我修改它来满足我的需求:

def traverse(dic, path=None): 
    if not path: 
     path=[] 
    if isinstance(dic,dict): 
     for x in dic.keys(): 
      local_path = path[:] 
      local_path.append(x) 
      for b in traverse(dic[x], local_path): 
       yield b 
    else: 
     yield path,dic 

最终的结果是我可以通过在一个JSON字符串,这样给我的脚本(带有可变深度),将它转换为嵌套类型的字典:

{ 
    "servers": { 
    "uat": { 
     "pkey": true, 
     "user": "testval", 
     "pass": true 
    }, 
    "dev": { 
     "pkey": true, 
     "user": "testval", 
     "pass": true 
    } 
    } 
} 

运行产生上述反对它创建一个列表,漂亮的版画是这样的:

([u'servers', u'uat', u'pkey'], True) 
([u'servers', u'uat', u'user'], u'testval') 
([u'servers', u'uat', u'pass'], True) 
([u'servers', u'dev', u'pkey'], True) 
([u'servers', u'dev', u'user'], u'testval') 
([u'servers', u'dev', u'pass'], True) 

其中,使用类似:

for x in traverse(outobj): 
    pprint(('.'.join(x[0]),x[1])) 

然后可以转化为键值对格式我想,像这样:

(u'servers.uat.pkey', True) 
(u'servers.uat.user', u'testval') 
(u'servers.uat.pass', True) 
(u'servers.dev.pkey', True) 
(u'servers.dev.user', u'testval') 
(u'servers.dev.pass', True) 

我知道我接受的答案后,发布这样被接受了,但由于接受的答案对我来说并不奏效,也许这个更轻微的结构不可知的版本会帮助别人!