파이썬

[Python] 목록 목록에서 플랫 목록을 만드는 방법은 무엇입니까?

zooheon 2022. 7. 31. 13:59
반응형

이 목록 목록을 평면화하고 싶습니다.

[[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]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 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)'
1000 loops, best of 3: 1.1 msec per loop

설명: 에 기반한 바로 가기는 +( 에서 암시적인 사용을 포함하여 sum) L 하위 목록이 있을 때 필연적으로 필요 O(L**2)합니다. 중간 결과 목록이 계속 길어지면 각 단계에서 새로운 중간 결과 목록 개체가 할당되고 모든 항목이 이전 중간 결과에서 복사해야 합니다(마지막에 몇 가지 새로운 결과가 추가됨). 따라서 단순함과 일반성의 실제 손실 없이 각각 I 항목의 L 하위 목록이 있다고 가정합니다. 총 사본 수는 1에서 L까지 제외된 x에 대한 x의 합을 I 곱한 것입니다. 즉, I * (L**2)/2.

목록 이해는 하나의 목록을 한 번만 생성하고 각 항목을 (원래 거주지에서 결과 목록으로) 정확히 한 번 복사합니다.

 

다음 을 사용할 수 있습니다 itertools.chain().

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

또는 연산자 itertools.chain.from_iterable()로 목록을 풀지 않아도 되는 which 를 사용할 수 있습니다 .*

>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))

이 접근 방식은 틀림없이 다음보다 더 읽기 쉽고 [item for sublist in l for item in sublist]더 빠른 것처럼 보입니다.

$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
20000 loops, best of 5: 10.8 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in l for item in sublist]'
10000 loops, best of 5: 21.7 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 5: 258 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;from functools import reduce' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 5: 292 usec per loop
$ python3 --version
Python 3.7.5rc1

 

작성자의 참고 사항 : 이것은 매우 비효율적입니다. 하지만 재미 있습니다. 모노이드 가 굉장하기 때문입니다.

>>> xss = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> sum(xss, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

sumiterable 의 요소를 합산하고 xss두 번째 인수를 합에 대한 초기 값으로 사용 []합니다. (기본 초기값은 0목록이 아닌 입니다.)

중첩 목록을 합산하기 때문에 실제로 [1,3]+[2,4]결과로 sum([[1,3],[2,4]],[]), 이는 와 같습니다 [1,3,2,4].

목록 목록에서만 작동합니다. 목록 목록의 경우 다른 솔루션이 필요합니다.

 

반응형