질문
저는 다음과 같은 리스트의 리스트가 있습니다.
[
[1, 2, 3],
[4, 5, 6],
[7],
[8, 9]
]
이것을 평평한 리스트인 [1, 2, 3, 4, 5, 6, 7, 8, 9]
로 만들 수 있을까요?
만약 리스트의 리스트가 중첩된 리스트 컴프리헨션에서 나온 것이라면, 컴프리헨션을 수정함으로써 더 간단하고 직접적으로 해결할 수 있습니다. 리스트 컴프리헨션에서 중첩된 리스트 대신 평평한 결과를 어떻게 얻을 수 있나요?를 참조하십시오.
여기에서 가장 인기 있는 솔루션들은 일반적으로 중첩된 리스트의 하나의 "레벨"만 평평하게 만듭니다. 일반적으로 재귀적으로 완전히 중첩된 구조를 완전히 평평하게 만드는 솔루션을 참조하려면 불규칙한(임의로 중첩된) 리스트의 리스트를 평평하게 만들기를 참조하십시오.
답변
리스트의 리스트 l
이 주어졌을 때,
flat_list = [item for sublist in l for item in sublist]
는 다음을 의미합니다:
flat_list = []
for sublist in l:
for item in sublist:
flat_list.append(item)
지금까지 게시된 단축키보다 빠릅니다. (l
은 펼칠 리스트입니다.)
다음은 해당 함수입니다:
def flatten(l):
return [item for sublist in l for item in sublist]
증거로, 표준 라이브러리의 timeit
모듈을 사용할 수 있습니다:
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
3회 중 최상의 10000회 루프: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
3회 중 최상의 1000회 루프: 969 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,l)'
3회 중 최상의 1000회 루프: 1.1 msec per loop
설명: +
를 기반으로 한 단축키(포함하여 sum
에서 암시적으로 사용되는 것)은 필연적으로 L 서브리스트가 있을 때 O(L**2)
입니다. 중간 결과 리스트가 계속 길어지므로 각 단계에서 새로운 중간 결과 리스트 객체가 할당되고 이전 중간 결과의 모든 항목이 복사되어야 합니다(끝에 새로운 항목이 추가됨). 따라서 간단하게 일반성을 잃지 않고, 각각 I 항목의 L 서브리스트가 있다고 가정합니다. 첫 I 항목은 L-1번, 두 번째 I 항목은 L-2번 등등 복사되며, 복사 횟수의 총합은 L을 제외한 1에서 L까지의 x의 합인 I * (L**2)/2
입니다.
리스트 컴프리헨션은 단지 한 번 리스트를 생성하고 각 항목을 (원래 위치에서 결과 리스트로) 정확히 한 번 복사합니다.
댓글