이중 리스트란 리스트 안에 리스트가 있은 것을 말한다. example_list = [[1, 2, 3], [4, 5, 6], [7, 8, 9]] 이중 리스트는 리스트 내의 특정 값을 찾거나 카운트할 때 인덱싱을 두 번 해야 하는 등 과정이 번거롭다. 이러한 이유로 이중 리스트를 1차원 리스트로 펼치는 방법에 대해 알아보도록 한다.
cf. 파이썬 코드의 실행 이미지는 ‘주피터 노트북’을 사용하였다.


1. List Comprehension

리스트 컴프리헨션(List Comprehension)은 리스트를 한 줄로 만들 수 있는 파이썬의 문법이다. 리스트 컴프리헨션을 통해 리스트 안에 있는 리스트 내의 요소들을 하나씩 담을 수 있다. 중첩된 반복문을 사용하여 리스트 내의 리스트들을 불러오고 그 리스트들의 요소들을 하나씩 불러오는 개념이다.

# 이중 리스트(lists)를 1차원으로 만드는 방법
[j for i in lists for j in i]
# 이해를 위해 리스트 컴프리헨션을 풀어서 작성해보았다.
new_list = []
for i in lists:
    for j in i:
        new_list.append(j)
예시: 리스트 컴프리헨션으로 이중 리스트를 1차원 리스트로 펼치는 과정


2. itertools 라이브러리

intertools 라이브러리에서 제공하는 chain 함수를 사용하면 이중 리스트를 1차원 리스트로 펼칠 수 있다. 이 방법을 사용하기 위해선 라이브러리를 불러오는 코드도 필요하다.

# 이중 리스트(lists)를 1차원으로 만드는 방법
from itertools import chain

list(chain(*lists))
예시: itertools 라이브러리로 이중 리스트를 1차원 리스트로 펼치는 과정


3. Sum 내장함수

Python의 내장함수인 sum을 사용해도 이중 리스트를 1차원 리스트로 펼칠 수 있다. sum의 두 번째 인수로 빈 리스트([])를 전달하면 첫 번째 인수로 전달한 리스트 앞에 아무것도 추가되지 않는다. 만약 빈 배열이 아닌 요소가 담긴 리스트를 두 번째 인수로 전달한다면 그 리스트 안에 담긴 요소들이 첫 번째 인수로 전달하는 리스트 앞에 담기게 된다.
예: sum([[1], [2]], [0]) >>> [0, 1, 2]

# 이중 리스트(lists)를 1차원으로 만드는 방법
sum(lists, [])
예시: sum 내장함수로 이중 리스트를 1차원 리스트로 펼치는 과정


4. Numpy 라이브러리

Numpy 라이브러리를 사용해도 이중 리스트를 1차원 리스트로 펼칠 수 있다. 이 방법을 통해 변환하려면 Numpy 라이브러리를 불러와야하고 기존의 이중 리스트를 numpy array로 변환하는 작업, flatten 작업, 다시 리스트로 변환하는 작업이 필요하다.
cf. Numpy 에는 2차원 배열을 1차원 배열로 펼치는 함수(flatten)가 존재한다.

# 이중 리스트(lists)를 1차원으로 만드는 방법
import numpy as np

np.array(lists).flatten().tolist()
예시: Numpy 라이브러리로 이중 리스트를 1차원 리스트로 펼치는 과정


⏳ 성능 테스트

파이썬 프로파일링으로 실행 속도를 비교하여 코드별 성능을 조사해보았다. 코드별로 여러 번(100000 loops) 실행하여 소요된 평균 time을 측정하였다(%timeit 사용)

코드별 파이썬 프로파일링 결과


프로파일링 결과를 보면 numpy로 이중 리스트를 1차원 리스트로 변경하는 과정이 가장 성능이 안좋다는 것을 알 수 있다(마이크로 단위는 10의 -6승, 나노 단위는 10의 -9승으로 마이크로 단위가 더 큼). 해석하기 쉽게 단위를 변환하여 보면 다음과 같다.

방법 성능 결과(per loop)
1. List Comprehension 448 ns ± 6.08 ns
2. itertools 라이브러리 306 ns ± 1.02 ns
3. Sum 내장함수 179 ns ± 0.817 ns
4. Numpy 라이브러리 2560 ns ± 16.1 ns

내장함수인 sum으로 이중 리스트를 1차원 리스트로 펼치는 과정이 Numpy로 변환하는 과정보다 약 14배 빠르다는 것을 알 수 있다. itertools 라이브러리를 통해 변환하는 과정에서 라이브러리를 불러올 때 from itertools import chain 으로 chain을 바로 불러왔는데 import itertools 로 실행해보았을 때 320 ns ± 1.7 ns per loop 의 결과가 나왔댜. 사용할 함수를 import 로 불러왔을 때가 기존대비 5% 정도 빠른 성능을 보인다는 결과를 얻었다.

👩🏻‍💻개인 공부 기록용 블로그입니다
오류나 틀린 부분이 있을 경우 댓글 혹은 메일로 따끔하게 지적해주시면 감사하겠습니다.

카테고리:

업데이트:

댓글남기기