문제

내가 있는지 궁금 바로 가기를 만드 간단한 목록의 목록에 있습니다.

내가 할 수 있는 것에 for 루프지만,어쩌면 거기에 몇 가지 멋진 하나"라"?나는 그것을 시도와 함께 을 줄일, 지만,나는 오류가 있습니다.

코드

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)

오류 메시지

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'
도움이 되었습니까?

해결책

목록 목록이 주어졌습니다 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 평평한 목록입니다.)

해당 기능은 다음과 같습니다.

flatten = lambda l: [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) 필요하고 O(L**2) L Subrist가있는 경우 - 중간 결과 목록이 계속 길어지면서 각 단계마다 새 중간 결과 목록 개체가 할당되고 이전 중간 결과의 모든 항목을 복사해야합니다 (몇 가지 새로운 항목은 추가되어야합니다. 결국). 따라서 단순성과 일반적인 일반적인 손실없이 각각 I 항목의 lsublist를 가지고 있다고 말합니다. 첫 번째 I 항목은 L-1 번, 두 번째 I 항목 L-2 회 등을 앞뒤로 복사합니다. 총 사본 수는 x의 x의 합이 1에서 l에서 제외됩니다. I * (L**2)/2.

목록 이해력은 한 번의 목록을 한 번 생성하고 각 항목을 원래 거주지에서 결과 목록에 이르기까지 정확히 한 번 복사합니다.

다른 팁

당신이 사용할 수있는 itertools.chain():

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

또는 Python> = 2.6에서 사용하십시오 itertools.chain.from_iterable() 목록을 풀 필요가없는 다음 :

>>> 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] 그리고 더 빠른 것 같습니다.

[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
10000 loops, best of 3: 24.2 usec per loop
[me@home]$ 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: 45.2 usec per loop
[me@home]$ python -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 3: 488 usec per loop
[me@home]$ 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: 522 usec per loop
[me@home]$ python --version
Python 2.7.3

저자의 참고 사항: 이것은 비효율적입니다. 그러나 재미 있습니다 모노이드 굉장한 데. 생산 파이썬 코드에는 적합하지 않습니다.

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

이것은 단지 첫 번째 인수에서 통과 된 반복 가능한 요소를 요약하여 두 번째 인수를 합의 초기 값으로 취급합니다 (주어지지 않은 경우, 0 대신 사용 되며이 케이스는 오류가 발생합니다).

중첩 된 목록을 합산하기 때문에 실제로 [1,3]+[2,4] 결과로 sum([[1,3],[2,4]],[]), 그것은 동일합니다 [1,3,2,4].

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

나는 가장 제안 된 솔루션을 테스트했습니다 perfplot (내 애완 동물 프로젝트, 본질적으로 포장지 timeit), 그리고 발견

functools.reduce(operator.iconcat, a, [])

가장 빠른 솔루션이 되십시오. (operator.iadd 똑같이 빠릅니다.)

enter image description here


플롯을 재현하기위한 코드 :

import functools
import itertools
import numpy
import operator
import perfplot


def forfor(a):
    return [item for sublist in a for item in sublist]


def sum_brackets(a):
    return sum(a, [])


def functools_reduce(a):
    return functools.reduce(operator.concat, a)


def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def numpy_concatenate(a):
    return list(numpy.concatenate(a))


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    kernels=[
        forfor, sum_brackets, functools_reduce, functools_reduce_iconcat,
        itertools_chain, numpy_flat, numpy_concatenate
        ],
    n_range=[2**k for k in range(16)],
    logx=True,
    logy=True,
    xlabel='num lists'
    )
from functools import reduce #python 3

>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(lambda x,y: x+y,l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

그만큼 extend() 예제의 메소드는 수정합니다 x 유용한 값을 반환하는 대신 ( reduce() 기대).

더 빠른 방법 reduce 버전이 될 것입니다

>>> import operator
>>> l = [[1,2,3],[4,5,6], [7], [8,9]]
>>> reduce(operator.concat, l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

다음은 적용되는 일반적인 접근법입니다 번호, 문자열, 중첩 목록 및 혼합 컨테이너.

암호

#from typing import Iterable 
from collections import Iterable                            # < py38


def flatten(items):
    """Yield items from any nested iterable; see Reference."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            for sub_x in flatten(x):
                yield sub_x
        else:
            yield x

메모:

  • Python 3에서 yield from flatten(x) 교체 할 수 있습니다 for sub_x in flatten(x): yield sub_x
  • Python 3.8에서 초록 기본 클래스 ~이다 움직이는 ~에서 collection.abc ~로 typing 기준 치수.

데모

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(lst))                                         # nested lists
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

mixed = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(mixed))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']

참조

  • 이 솔루션은 레시피에서 수정됩니다 Beazley, D. 및 B. Jones. 레시피 4.14, Python Cookbook 3rd ed., O'Reilly Media Inc. Sebastopol, CA : 2013.
  • 이전을 찾았습니다 그래서 게시, 아마도 원래 데모 일 것입니다.

당신이 얼마나 깊은지 모르는 데이터 구조를 평평하게하려면 사용할 수 있습니다. iteration_utilities.deepflatten1

>>> from iteration_utilities import deepflatten

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(deepflatten(l, depth=1))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

>>> l = [[1, 2, 3], [4, [5, 6]], 7, [8, 9]]
>>> list(deepflatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

생성기이므로 결과를 list 또는 명시 적으로 반복합니다.


한 레벨 만 평평하게하고 각 항목 자체가 반복되면 사용할 수도 있습니다. iteration_utilities.flatten 그 자체는 단지 얇은 포장지입니다 itertools.chain.from_iterable:

>>> from iteration_utilities import flatten
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> list(flatten(l))
[1, 2, 3, 4, 5, 6, 7, 8, 9]

일부 타이밍을 추가하려면 (이 답변에 제시된 기능이 포함되지 않은 Nico Schlömer 답변을 기반으로) :

enter image description here

그것은 거대한 범위의 값을 수용 할 수있는 로그 로그 플롯입니다. 질적 추론의 경우 : 낮은 것이 더 좋습니다.

결과는 반짝이가 안에있는 반복성 만 포함한다면 sum 그러나 가장 빠른 것은하지만 긴 반복은 itertools.chain.from_iterable, iteration_utilities.deepflatten 또는 중첩 이해는 합리적인 성능을 가지고 있습니다 itertools.chain.from_iterable 가장 빠른 것입니다 (Nico Schlömer가 이미 알아 차린 것처럼).

from itertools import chain
from functools import reduce
from collections import Iterable  # or from collections.abc import Iterable
import operator
from iteration_utilities import deepflatten

def nested_list_comprehension(lsts):
    return [item for sublist in lsts for item in sublist]

def itertools_chain_from_iterable(lsts):
    return list(chain.from_iterable(lsts))

def pythons_sum(lsts):
    return sum(lsts, [])

def reduce_add(lsts):
    return reduce(lambda x, y: x + y, lsts)

def pylangs_flatten(lsts):
    return list(flatten(lsts))

def flatten(items):
    """Yield items from any nested iterable; see REF."""
    for x in items:
        if isinstance(x, Iterable) and not isinstance(x, (str, bytes)):
            yield from flatten(x)
        else:
            yield x

def reduce_concat(lsts):
    return reduce(operator.concat, lsts)

def iteration_utilities_deepflatten(lsts):
    return list(deepflatten(lsts, depth=1))


from simple_benchmark import benchmark

b = benchmark(
    [nested_list_comprehension, itertools_chain_from_iterable, pythons_sum, reduce_add,
     pylangs_flatten, reduce_concat, iteration_utilities_deepflatten],
    arguments={2**i: [[0]*5]*(2**i) for i in range(1, 13)},
    argument_name='number of inner lists'
)

b.plot()

1 면책 조항 : 저는 해당 도서관의 저자입니다

나는 나의 문이다.sum 하지 않은 승리자입니다.비록 그것이 더 빨리 목록이 작습니다.그러나 성능 저하와 함께 크게 더 큰 목록이 있습니다.

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10000'
    ).timeit(100)
2.0440959930419922

Sum 버전은 여전히 이상 실행하고 그것은 하지 않았 처리다.

중간 나열:

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
20.126545906066895
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
22.242258071899414
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]] * 10'
    ).timeit()
16.449732065200806

작은 사용하여 나열하고 시간:number=1000000

>>> timeit.Timer(
        '[item for sublist in l for item in sublist]',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
2.4598159790039062
>>> timeit.Timer(
        'reduce(lambda x,y: x+y,l)',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.5289170742034912
>>> timeit.Timer(
        'sum(l, [])',
        'l=[[1, 2, 3], [4, 5, 6, 7, 8], [1, 2, 3, 4, 5, 6, 7]]'
    ).timeit()
1.0598428249359131

혼란이있는 것 같습니다 operator.add! 두 목록을 함께 추가하면 올바른 용어는 concat, 추가하지 않습니다. operator.concat 사용해야 할 것입니다.

당신이 기능적이라고 생각한다면, 이것만큼 쉽습니다 ::

>>> from functools import reduce
>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)

서열 유형에 대한 존중이 줄어 듭니다. 따라서 튜플을 공급할 때 튜플을 되 찾습니다. 목록으로 시도해 봅시다 ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

아하, 목록을 되 찾으십시오.

성능은 어떻습니까 ::

>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> %timeit list(itertools.chain.from_iterable(list2d))
1000000 loops, best of 3: 1.36 µs per loop

from_iterable 꽤 빠릅니다! 그러나 감소하는 것은 비교가 아닙니다 concat.

>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop

Extend를 사용하는 이유는 무엇입니까?

reduce(lambda x, y: x+y, l)

이것은 잘 작동해야합니다.

설치를 고려하십시오 more_itertools 패키지.

> pip install more_itertools

구현과 함께 배송됩니다 flatten (원천, 로부터 itertools 레시피):

import more_itertools


lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.flatten(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

버전 2.4 기준으로 더 복잡하고 중첩 된 반복을 평평하게 할 수 있습니다. more_itertools.collapse (원천, Abarnet에 의해 기여).

lst = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(more_itertools.collapse(lst)) 
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

lst = [[1, 2, 3], [[4, 5, 6]], [[[7]]], 8, 9]              # complex nesting
list(more_itertools.collapse(lst))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

기능이 작동하지 않은 이유 : 확장은 배열을 배열 내에서 확장하여 반환하지 않습니다. 몇 가지 트릭을 사용하여 Lambda에서 X를 반환 할 수 있습니다.

reduce(lambda x,y: x.extend(y) or x, l)

참고 : 확장은 목록에서 +보다 효율적입니다.

사용중인 경우 바퀴를 재발 명하지 마십시오 장고:

>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]

...팬더:

>>> from pandas.core.common import flatten
>>> list(flatten(l))

...Itertools:

>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))

...matplotlib

>>> from matplotlib.cbook import flatten
>>> list(flatten(l))

...Unipath:

>>> from unipath.path import flatten
>>> list(flatten(l))

...SetUptools:

>>> from setuptools.namespaces import flatten
>>> list(flatten(l))
def flatten(l, a):
    for i in l:
        if isinstance(i, list):
            flatten(i, a)
        else:
            a.append(i)
    return a

print(flatten([[[1, [1,1, [3, [4,5,]]]], 2, 3], [4, 5],6], []))

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

위의 ANIL 기능의 나쁜 특징은 사용자가 항상 두 번째 인수를 빈 목록으로 수동으로 지정해야한다는 것입니다. []. 대신 기본값이어야합니다. 파이썬 객체가 작동하는 방식으로 인해 인수가 아닌 함수 내부에서 설정해야합니다.

작동 기능은 다음과 같습니다.

def list_flatten(l, a=None):
    #check a
    if a is None:
        #initialize with empty list
        a = []

    for i in l:
        if isinstance(i, list):
            list_flatten(i, a)
        else:
            a.append(i)
    return a

테스트 :

In [2]: lst = [1, 2, [3], [[4]],[5,[6]]]

In [3]: lst
Out[3]: [1, 2, [3], [[4]], [5, [6]]]

In [11]: list_flatten(lst)
Out[11]: [1, 2, 3, 4, 5, 6]

matplotlib.cbook.flatten() 중첩 된 목록은 예보다 깊게 중첩 되더라도 작동합니다.

import matplotlib
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
print(list(matplotlib.cbook.flatten(l)))
l2 = [[1, 2, 3], [4, 5, 6], [7], [8, [9, 10, [11, 12, [13]]]]]
print list(matplotlib.cbook.flatten(l2))

결과:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

이것은 밑줄보다 18 배 빠릅니다 ._. 평평한 :

Average time over 1000 trials of matplotlib.cbook.flatten: 2.55e-05 sec
Average time over 1000 trials of underscore._.flatten: 4.63e-04 sec
(time for underscore._)/(time for matplotlib.cbook) = 18.1233394636

변수 길이의 텍스트 기반 목록을 다룰 때 허용 된 답변은 저에게 효과가 없었습니다. 다음은 저에게 효과가있는 대체 접근 방식입니다.

l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]

수락 된 답변 ~ 아니다 일하다:

flat_list = [item for sublist in l for item in sublist]
print(flat_list)
['a', 'a', 'a', 'b', 'b', 'c', 'c', 'c', 'c', 'c', 'c', 'xx', 'yyyyyyy']

새로운 제안 된 솔루션 했다 나를 위해 일 :

flat_list = []
_ = [flat_list.extend(item) if isinstance(item, list) else flat_list.append(item) for item in l if item]
print(flat_list)
['aaa', 'bb', 'cccccc', 'xx', 'yyyyyyy']

재귀 버전

x = [1,2,[3,4],[5,[6,[7]]],8,9,[10]]

def flatten_list(k):
    result = list()
    for i in k:
        if isinstance(i,list):

            #The isinstance() function checks if the object (first argument) is an 
            #instance or subclass of classinfo class (second argument)

            result.extend(flatten_list(i)) #Recursive call
        else:
            result.append(i)
    return result

flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]

다음은 나에게 가장 단순 해 보인다 :

>>> import numpy as np
>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> print (np.concatenate(l))
[1 2 3 4 5 6 7 8 9]

Numpy 's도 사용할 수 있습니다 평평한:

import numpy as np
list(np.array(l).flat)

편집 11/02/2016 : 하위 목록에 동일한 치수가있는 경우에만 작동합니다.

Numpy를 사용할 수 있습니다.
flat_list = list(np.concatenate(list_of_list))

간단한 코드 underscore.py 패키지 팬

from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

모든 평평한 문제를 해결합니다 (없음 목록 항목 또는 복잡한 중첩)

from underscore import _
# 1 is none list item
# [2, [3]] is complex nesting
_.flatten([1, [2, [3]], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

설치할 수 있습니다 underscore.py PIP와 함께

pip install underscore.py
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])
flat_list = []
for i in list_of_list:
    flat_list+=i

이 코드는 목록을 끝까지 확장하므로 잘 작동합니다. 비슷하지만 루프 용은 하나만 있습니다. 따라서 루프에 2를 추가하는 것보다 복잡성이 적습니다.

더 깨끗한 외관을 위해 소량의 속도를 기꺼이 포기한다면, 당신은 사용할 수 있습니다. numpy.concatenate().tolist() 또는 numpy.concatenate().ravel().tolist():

import numpy

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]] * 99

%timeit numpy.concatenate(l).ravel().tolist()
1000 loops, best of 3: 313 µs per loop

%timeit numpy.concatenate(l).tolist()
1000 loops, best of 3: 312 µs per loop

%timeit [item for sublist in l for item in sublist]
1000 loops, best of 3: 31.5 µs per loop

문서에서 더 많은 것을 찾을 수 있습니다 numpy.concatenate 그리고 Numpy.Ravel

내가 찾은 가장 빠른 솔루션 (어쨌든 큰 목록의 경우) :

import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()

완료! 물론 목록 (L)을 실행하여 목록으로 되돌릴 수 있습니다.

이것은 가장 효율적인 방법이 아니지만 1 라이너 (실제로 2 라이너)를 넣는 것으로 생각했습니다. 두 버전 모두 임의의 계층 중첩 된 목록에서 작동하며 언어 기능 (Python3.5) 및 재귀를 이용합니다.

def make_list_flat (l):
    flist = []
    flist.extend ([l]) if (type (l) is not list) else [flist.extend (make_list_flat (e)) for e in l]
    return flist

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = make_list_flat(a)
print (flist)

출력은입니다

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

이것은 깊이있는 첫 번째 방식으로 작동합니다. 재귀는 비 목록 요소를 찾을 때까지 내려 가고 로컬 변수를 확장합니다. flist 그런 다음 부모에게 롤백합니다. 언제든지 flist 반품되면 부모의 것으로 확장됩니다. flist 목록 이해력에서. 따라서 루트에서는 평평한 목록이 반환됩니다.

위의 하나는 여러 로컬 목록을 생성하고 부모의 목록을 확장하는 데 사용되는 리턴을 반환합니다. 나는 이것을위한 길이 Gloabl을 만들 수 있다고 생각합니다 flist, 아래와 마찬가지로.

a = [[1, 2], [[[[3, 4, 5], 6]]], 7, [8, [9, [10, 11], 12, [13, 14, [15, [[16, 17], 18]]]]]]
flist = []
def make_list_flat (l):
    flist.extend ([l]) if (type (l) is not list) else [make_list_flat (e) for e in l]

make_list_flat(a)
print (flist)

출력이 다시 있습니다

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]

지금은 효율성에 대해 확신하지 못합니다.

메모: 아래는 Python 3.3+가 사용되므로 적용됩니다 yield_from. six 안정적이지만 타사 패키지이기도합니다. 또는 사용할 수 있습니다 sys.version.


의 경우 obj = [[1, 2,], [3, 4], [5, 6]], 여기의 모든 솔루션은 목록 이해력과 itertools.chain.from_iterable.

그러나이 약간 더 복잡한 경우를 고려하십시오.

>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]

여기에는 몇 가지 문제가 있습니다.

  • 하나의 요소, 6, 단지 스칼라입니다. 반복 할 수 없으므로 위의 경로가 여기에서 실패합니다.
  • 하나의 요소, 'abc', ~이다 기술적으로 반복적 인 (모두 strs). 그러나 줄 사이를 조금 읽으면 그것을 그렇게 취급하고 싶지 않습니다. 단일 요소로 취급하고 싶습니다.
  • 최종 요소, [8, [9, 10]] 그 자체는 중첩 된 반복적입니다. 기본 목록 이해력 및 chain.from_iterable "1 레벨 다운"만 추출합니다.

다음과 같이 이것을 해결할 수 있습니다.

>>> from collections import Iterable
>>> from six import string_types

>>> def flatten(obj):
...     for i in obj:
...         if isinstance(i, Iterable) and not isinstance(i, string_types):
...             yield from flatten(i)
...         else:
...             yield i


>>> list(flatten(obj))
[1, 2, 3, 4, 5, 6, 'abc', 7, 8, 9, 10]

여기에서 하위 요소 (1)가 반복 할 수 있는지 확인합니다. Iterable, ABC itertools, 그러나 (2) 요소가 ~ 아니다 "문자열 같은."

이종 및 균질 한 정수 목록에 작용하는 또 다른 특이한 접근법 :

from typing import List


def flatten(l: list) -> List[int]:
    """Flatten an arbitrary deep nested list of lists of integers.

    Examples:
        >>> flatten([1, 2, [1, [10]]])
        [1, 2, 1, 10]

    Args:
        l: Union[l, Union[int, List[int]]

    Returns:
        Flatted list of integer
    """
    return [int(i.strip('[ ]')) for i in str(l).split(',')]

단순 재귀적 방법을 사용하여 reducefunctoolsadd 운영자에 나열:

>>> from functools import reduce
>>> from operator import add
>>> flatten = lambda lst: [lst] if type(lst) is int else reduce(add, [flatten(ele) for ele in lst])
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

기능 flatten 에 걸리 lst 으로 매개 변수입니다.그것은 루프의 모든 요소 lst 에 도달할 때까지 정수(수 있도 변경 int 하기 float, str, 니다,등등.기타 데이터 형식)에 추가하여 반환 값의 가장 바깥쪽 재귀.

재귀와는 달리,과 같은 방법 for 루프를 사용해,그것은 일반적인 솔루션에 의해 제한되지 않 목록 깊이.예를 들어,목록과 깊이의 5 결과 같은 방법으로 l:

>>> l2 = [[3, [1, 2], [[[6], 5], 4, 0], 7, [[8]], [9, 10]]]
>>> flatten(l2)
[3, 1, 2, 6, 5, 4, 0, 7, 8, 9, 10]
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top