2016-09-19 1 views
1

와 문제 :파이썬 - 계층 구조/여러 중첩 된 dicts에 dicts의 목록을 변환 - 현재 나는이 입력이 주문

query = [{'id': 1, 'desc': 'desc_father', 'parent_id': None} 
     ,{'id': 2, 'desc': 'desc_child_1', 'parent_id': 10} 
     ,{'id': 3, 'desc': 'desc_child_2', 'parent_id': 2} 
     ,{'id': 4, 'desc': 'desc_child_5', 'parent_id': 5} 
     ,{'id': 5, 'desc': 'desc_child_6', 'parent_id': 6} 
     ,{'id': 6, 'desc': 'desc_child_1', 'parent_id': 1}] 

이 내 재귀 함수입니다 : 이것은 내 주요 코드가

def recursive(parent_list, child_dict, parent_id): 
    for l in parent_list: 
     if parent_id in l.values(): 
      if 'children' not in l: 
       l['children'] = [] 
      l['children'].append(child_dict) 
      break 
     else: 
      for i in l: 
       if isinstance(l[i], list): 
        recursive(d[i], child_dict, parent_id) 
    return parent_list 

입니다 :

results = [] 
for q in query: 
    dict_item = {} 
    dict_item['id'] = q['id'] 
    dict_item['desc'] = q['desc'] 
    if q['parent_id'] is None: 
     results.append(dict_item) 
    else: 
     results= recursive(results, dict_item, q['parent_id']) 
return results 

그래서, 위에 주어진 데이터와 코드, 나는 다음과 같은 결과를 가지고 :

이 때문에 루프 동안, 이러한 항목의 부모가 아직 생성되지 않은 id = 4id = 5와 누락 된 항목을 참조하십시오 (항목 id = 5 & id = 6 포함) 수 있기
[{ 
     'desc' : 'desc_father', 
     'id' : 1, 
     'children' : [{ 
       'desc' : 'desc_child_1', 
       'id' : 2, 
       'children' : [{ 
         'desc' : 'desc_child_2', 
         'id' : 3 
        } 
       ] 
      }, { 
       'desc' : 'desc_child_1', 
       'id' : 6 
      } 
     ] 
    } 
] 

이 결과입니다. 나는이 문제를 해결하는데 어려움을 겪고있다. 나는 아이들을 만들기 전에 아버지 항목을 만들기 위해 목록을 되돌려 보내거나 전달하는 방법을 모른다. 도움을 주시면 감사하겠습니다. 미리 감사드립니다.

내가 id = 2와 항목이 내 쿼리에 대해 하나의 경우에 추가 한

업데이트, 우리는을 가지고 있지 않기 때문에 항목이, 10 (parent_id = 10)에 자사의 PARENT_ID 업데이트되는이 시간 반환 결과에 id = 10이있는 부모 항목이므로이 id = 2 항목도 루트가됩니다.

내 새 코드는 Scott Hunter 지침을 기반으로 작성되었지만 여전히 작동하지는 못합니다. 어디 선가 오해합니다

new_dict = {} 
for q in query: 
    q['Children'] = [] 
    new_dict[q['id']] = q 

for k, v in new_dict.iteritems(): 
    print k, v 
    if v['parent_id'] is not None and v['parent_id'] in new_dict: 
     new_dict[k]['Children'].append(v) 

print new_dict 

업데이트-2

지금 내가 스콧 헌터의 제안에 따라 작동 할 수 있도록, 내 아래 코드를 참조하십시오. 그러나 코드가 너무 많아서보기 싫어서 어쨌든 내가 이것을 완벽하게 만들 수 있습니까? 귀하의 지원에 많은 시간을 보내 주셔서 감사 드리며, 한 단계 더 나아갈 것입니다!

new_dict = {} 

for q in query: 
    q['children'] = [] 
    q['parent'] = 1 
    new_dict[q['id']] = q 

for k, v in new_dict.iteritems(): 
    p_id = v['parent_id'] 
    for kk, vv in new_dict.iteritems(): 
     if kk == p_id: 
      v['parent'] = 0 
      vv['children'].append(v) 

results = [] 

for d_id, d_item in new_dict.iteritems(): 
    if d_item['parent'] == 1: 
     results.append(d_item) 

print results 
+0

왜 'v'를 자체 자식 중 하나로 만드나요? –

+0

안녕하세요 @ ScottHunter, 나는 그것을 만들었습니다. 내 코드를 검토해 주시겠습니까? 고맙습니다. – Leo

답변

2

이것은 재귀를 필요로하지 않습니다.

처음 노드의 사전을 만듭니다. 노드의 사전은 빈 항목 목록을 포함하는 id을 키로 사용하여 각 항목에 하나씩 만듭니다. 그런 다음 해당 사전을 스캔하고 각 노드를 상위 항목에 대한 자식 목록에 추가합니다 (부모가 None 인 항목 제외). 이 검사가 완료되면 루트가 아닌 모든 노드가 상위 노드의 하위 목록에 있으므로 모든 트리가 완료됩니다.

forrest의 루트는 부모 노드에 None 인 노드입니다.

+0

답장을 보내 주신 고맙습니다 @ 스콧 헌터. 불행히도 나는 당신의 대답을 이해할 수 없습니다. 더 잘 이해할 수 있도록 도와 주실 수 있겠습니까? 귀하의 대답에 따르면, 자식 노드는 여전히 아버지 노드로 결과에있을 수 있지만, 처음에는 각 트리의 아버지 만 필요합니다. 샘플 입력에는 하나의 아버지 노드 만 있지만 실제로는 'parent_id : None'이 둘 이상일 수 있습니다. – Leo

+0

업데이트 된 답변을 보내 주셔서 감사하지만 코드 스 니펫이 있습니까? 나는 이것을 몇 시간 동안 고민해왔다. 당신의 대답에 따라, 나는 레벨 3 이상을 만들 수 없었다. 그들은 모두 레벨 2에 있습니다. 고마워요. – Leo

+0

업데이트 된 코드를 게시하십시오. –

1

이 내 해결책이 될 것입니다 :

#! /usr/bin/env python3 
from pprint import pprint 
query = [{'id': 1, 'desc': 'desc_father', 'parent_id': None} 
     ,{'id': 2, 'desc': 'desc_child_1', 'parent_id': 1} 
     ,{'id': 3, 'desc': 'desc_child_2', 'parent_id': 2} 
     ,{'id': 4, 'desc': 'desc_child_5', 'parent_id': 5} 
     ,{'id': 5, 'desc': 'desc_child_6', 'parent_id': 6} 
     ,{'id': 6, 'desc': 'desc_child_1', 'parent_id': 1}] 


def rec(query, parent): 
    parent['children'] = [] 
    for item in query: 
     if item['parent_id'] == parent['id']: 
      parent['children'].append(item) 
      rec(query, item) 


root = {'id': None} 
rec(query, root) 

pprint(root, indent=4) 

그것은 나에게 출력 제공 (키 순서가 있습니다,하지만 그건 당신이 사전을 사용할 때 당신은 무엇을 얻을)

[email protected]:~/Dev/random$ python recursion_tree.py 
{ 'children': [ { 'children': [ { 'children': [], 
              'desc': 'desc_child_2', 
              'id': 3, 
              'parent_id': 2}], 
         'desc': 'desc_child_1', 
         'id': 2, 
         'parent_id': 1}, 
        { 'children': [ { 'children': [ { 'children': [ ], 
                   'desc': 'desc_child_5', 
                   'id': 4, 
                   'parent_id': 5}], 
              'desc': 'desc_child_6', 
              'id': 5, 
              'parent_id': 6}], 
         'desc': 'desc_child_1', 
         'id': 6, 
         'parent_id': 1}], 
    'desc': 'desc_father', 
    'id': 1, 
    'parent_id': None} 

이해야 심지어 여러 루트 노드로 작업 할 수 있습니다 (상단에 ID가 None 인 더미 노드가 있음)

관련 문제