Computer >> 컴퓨터 >  >> 프로그래밍 >> Python

Python 중첩 리스트를 트리 구조 딕셔너리로 변환하는 방법

중첩 리스트(nested list)가 주어졌을 때, 이를 트리(tree) 자료구조처럼 표현할 수 있는 딕셔너리로 변환해야 하는 경우가 있습니다. 예를 들어 ['P', 'Z', 'X']와 같은 경로 정보를 계층형 구조로 만들고 싶다면, 각 요소를 부모-자식 관계로 연결된 딕셔너리로 재구성하면 됩니다.

이 글에서는 중첩 리스트를 트리 형태의 딕셔너리로 변환하는 두 가지 방법을 소개합니다.

방법 1: 슬라이싱(Slicing) 활용

첫 번째 방법은 슬라이싱을 사용해 리스트의 요소 순서를 뒤집은 뒤, 각 요소를 순회하면서 트리에 추가하는 방식입니다. 이미 존재하지 않는 키라면 새로운 빈 딕셔너리를 생성하고, 존재한다면 기존 노드를 따라 내려갑니다.

예제 코드

def CreateTree(lst):
    new_tree = {}
    for list_item in lst:
        currTree = new_tree

        for key in list_item[::-1]:
            if key not in currTree:
                currTree[key] = {}
            currTree = currTree[key]
    return new_tree

# 주어진 리스트
listA = [['X'], ['Y', 'X'], ['Z', 'X'], ['P', 'Z', 'X']]
print(CreateTree(listA))

실행 결과

{'X': {'Y': {}, 'Z': {'P': {}}}}

위 코드에서는 각 하위 리스트를 역순으로 순회하며 'X'를 루트로 삼는 트리를 구성합니다. 그 결과 'Y'와 'Z'가 'X'의 자식 노드로, 다시 'P'가 'Z'의 자식 노드로 배치된 것을 확인할 수 있습니다.

방법 2: reduce와 getitem 활용

두 번째 방법은 functools 모듈의 reduce 함수와 operator 모듈의 getitem 함수를 조합하는 방식입니다. 이 두 함수를 이용해 리스트에서 값을 읽어오는 함수(getTree)와 트리에 값을 설정하는 함수(setTree)를 정의할 수 있습니다.

여기서도 마찬가지로 슬라이싱으로 리스트 요소의 순서를 뒤집은 후, 앞서 정의한 두 함수를 적용하여 트리 구조의 딕셔너리를 생성합니다.

예제 코드

from functools import reduce
from operator import getitem

def getTree(tree, mappings):
    return reduce(getitem, mappings, tree)

def setTree(tree, mappings):
    getTree(tree, mappings[:-1])[mappings[-1]] = dict()

# 주어진 리스트
lst = [['X'], ['Y', 'X'], ['Z', 'X'], ['P', 'Z', 'X']]
tree = {}
for i in lst:
    setTree(tree, i[::-1])
print(tree)

실행 결과

{'X': {'Y': {}, 'Z': {'P': {}}}}

getTree 함수는 reduce를 통해 매핑 경로를 따라 기존 노드까지 접근하고, setTree 함수는 마지막 위치에 새로운 빈 딕셔너리를 할당하여 노드를 추가합니다. 두 방법 모두 동일한 결과를 출력하며, 코드 스타일과 가독성 측면에서 선호하는 방식을 선택하면 됩니다.