개발/Python 스터디

[Python] 중첩 리스트 펼치기(Nested List Flattening): 복잡한 데이터 구조를 간단하게!

0171-cloud 2024. 11. 27. 09:00

Python 중첩 리스트 펼치기(Nested List Flattening): 복잡한 데이터 구조를 간단하게!

중첩 리스트(Nested List)는 리스트 안에 또 다른 리스트가 포함된 데이터 구조로, 다차원 데이터를 표현하거나 복잡한 데이터 처리를 할 때 자주 등장합니다. 그러나 중첩된 리스트는 데이터를 다루는 과정을 복잡하게 만들기 때문에, 이를 한 차원으로 펼치는 작업(Flattening)이 필요합니다.

이번 글에서는 중첩 리스트를 간단히 펼치는 방법과 함께, 딥러닝이나 데이터 전처리 같은 실제 코드 상황에서 유용하게 활용할 수 있는 예제를 소개합니다.


중첩 리스트란 무엇인가?

중첩 리스트는 리스트 안에 또 다른 리스트가 포함된 구조를 말합니다. 예를 들어:

nested_list = [[1, 2, [3, 4]], [5, 6], 7]

위와 같은 중첩 리스트는 다차원 데이터를 표현하거나 계층적인 정보를 담는 데 유용하지만, 데이터를 한 차원으로 펼쳐야 할 경우 복잡한 작업이 필요합니다.


기본 중첩 리스트 펼치기 방법: 재귀 함수 사용

중첩 리스트를 펼치려면 재귀 함수를 사용하는 것이 기본적이고 가장 직관적인 방법입니다. 아래 예제는 중첩 리스트를 한 차원으로 만드는 간단한 재귀 함수를 보여줍니다.

def flatten_list(nested):
    for item in nested:
        if isinstance(item, list):
            yield from flatten_list(item)  # 재귀적으로 내부 리스트를 처리
        else:
            yield item

# 실행 예시
nested_list = [[1, 2, [3, 4]], [5, 6], 7]
flattened = list(flatten_list(nested_list))
print(flattened)

출력 결과

[1, 2, 3, 4, 5, 6, 7]

설명

  • flatten_listyield from을 사용해 중첩된 리스트를 재귀적으로 순회합니다.
  • 리스트가 아니면 값을 반환(yield)하고, 리스트라면 다시 함수 호출을 통해 내부 리스트를 처리합니다.
  • 이 방식은 중첩된 깊이에 상관없이 모든 데이터를 한 차원으로 펼칠 수 있습니다.

딥러닝 데이터 전처리에서 중첩 리스트 펼치기

딥러닝 모델을 다룰 때, 중첩된 리스트 형태의 데이터를 Flatten해야 하는 경우가 자주 있습니다. 예를 들어, 이미지 데이터나 텍스트 데이터가 계층적으로 저장되어 있을 때 이를 한 차원으로 펼쳐 모델에 입력해야 합니다.

예제: 중첩 리스트로 저장된 배치 데이터 펼치기

def flatten_batch_data(batch_data):
    for batch in batch_data:
        if isinstance(batch, list):
            yield from flatten_batch_data(batch)  # 재귀적으로 배치 데이터를 펼침
        else:
            yield batch

# 딥러닝 배치 데이터 예시
nested_batches = [
    [[1, 2], [3, 4]],  # 배치 1
    [5, [6, 7]],       # 배치 2
    8                  # 배치 3
]

flattened_data = list(flatten_batch_data(nested_batches))
print(flattened_data)

출력 결과

[1, 2, 3, 4, 5, 6, 7, 8]

설명

  • flatten_batch_data는 딥러닝 배치 데이터를 한 차원으로 펼칩니다.
  • 모델에 데이터를 입력할 때 중첩된 구조를 제거해야 한다면 이런 방식이 유용합니다.

리스트 컴프리헨션으로 중첩 리스트 펼치기

리스트 컴프리헨션은 짧고 간결한 코드 작성을 가능하게 하지만, 중첩 구조가 깊지 않을 때 적합합니다. 아래는 간단한 2차원 리스트를 펼치는 예제입니다.

nested_list = [[1, 2], [3, 4], [5, 6]]

# 리스트 컴프리헨션을 사용한 플래튼
flattened = [item for sublist in nested_list for item in sublist]
print(flattened)

출력 결과

[1, 2, 3, 4, 5, 6]

설명

  • 리스트 컴프리헨션을 사용하면 중첩 리스트의 각 요소를 한 줄로 펼칠 수 있습니다.
  • 하지만 깊이가 2 이상인 중첩 리스트에는 적합하지 않습니다. 이 경우 재귀 함수가 필요합니다.

중첩 리스트를 펼칠 때 itertools 활용하기

Python의 itertools 모듈은 복잡한 데이터 처리에 유용하며, 중첩 리스트를 처리할 때도 활용할 수 있습니다.

from itertools import chain

nested_list = [[1, 2], [3, 4], [5, 6]]

# itertools.chain으로 리스트 펼치기
flattened = list(chain.from_iterable(nested_list))
print(flattened)

출력 결과

[1, 2, 3, 4, 5, 6]

설명

  • itertools.chain.from_iterable은 리스트의 각 요소를 펼쳐줍니다.
  • 리스트의 깊이가 2차원인 경우 유용하며, 이 이상의 깊이는 재귀가 필요합니다.

실전 응용: 중첩된 JSON 데이터를 펼쳐보기

복잡한 JSON 데이터를 다룰 때 중첩된 리스트를 펼쳐야 할 경우도 있습니다. 아래는 JSON 데이터에서 리스트를 Flatten하는 예제입니다.

import json

# JSON 데이터 예시
json_data = '''
[
    {"name": "Alice", "scores": [10, 20, [30, 40]]},
    {"name": "Bob", "scores": [50, [60, 70]]}
]
'''

# JSON 파싱 및 플래튼
data = json.loads(json_data)

def flatten_json_scores(data):
    for entry in data:
        yield entry["name"], list(flatten_list(entry["scores"]))

# 실행
flattened_scores = list(flatten_json_scores(data))
print(flattened_scores)

출력 결과

[('Alice', [10, 20, 30, 40]), ('Bob', [50, 60, 70])]

설명

  • JSON 데이터를 파싱한 뒤 flatten_list를 사용해 각 scores를 펼칩니다.
  • 복잡한 JSON 데이터 구조를 Flatten하여 데이터를 쉽게 다룰 수 있도록 합니다.

결론: 중첩 리스트 펼치기의 다양한 활용

Python에서 중첩 리스트를 펼치는 작업은 데이터 전처리, 딥러닝, JSON 데이터 처리 등 다양한 상황에서 필수적입니다. 이번 가이드에서 소개한 방법들을 상황에 맞게 선택해 사용하세요:

  1. 재귀 함수: 깊이가 무제한인 중첩 리스트를 펼칠 때.
  2. 리스트 컴프리헨션: 깊이가 2인 리스트를 간단히 펼칠 때.
  3. itertools.chain: 2차원 리스트를 빠르게 펼칠 때.
  4. 딥러닝 데이터 처리: 배치 데이터를 펼쳐 모델에 입력할 때.