2012-08-13 5 views
2

내가 같은 사전이 있습니다중첩 된 사전을 탐색하고 파이썬에서 경로를 얻으시겠습니까?

{ 
    "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과 폴더를 넣을 수 있습니다.

는 지금은 모든 하위 폴더의 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

idention을 사용하여 사전을 포맷 해 주실 수 있습니까? 그리고 귀하의 질문을 이해할 필요가없는 모든 것을 제발 제거 할 수 있습니까? –

+0

사전을 읽을 수 있습니다. –

+1

예상 출력은 무엇입니까 – Rakesh

답변

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

나는이 줄을 생각하고 있었다. ''TypeError''가 i (': type' ')'에서 dict (보통 :-) 인 경우 고통을 겪을 것이므로 여전히 작업이 필요합니다. – azhrei

+0

좋습니다. 그것은 완벽하게 작동하지 않지만 나에게 아이디어를 줘. 감사! –

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 

최종 결과는 내가 통과 할 수있다 중첩 dicts로 변환 (가변 깊이가) 내 스크립트에이 같은 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) 

받아 들여졌지만, 받아 들인 대답이 나에게 도움이되지 않았기 때문에 아마도이 구조가 더 이상적이지 않은이 버전이 다른 누군가를 도울 것입니다!

관련 문제