Jak zrobić płaską listę z listy list?

Zastanawiam się, czy istnieje skrót do zrobienia prostej listy z listy list w Pythonie.

Mogę to zrobić w for pętli, ale może jest jakiś fajny "one-liner"? Próbowałem z reduce(), ale dostaję błąd.

Kod

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

Komunikat o błędzie

Traceback (most recent call last):
  File "<stdin>", line 1, in <module>
  File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'
Author: martineau, 2009-06-04

30 answers

Podano listę list t,

flat_list = [item for sublist in t for item in sublist]

Co oznacza:

flat_list = []
for sublist in t:
    for item in sublist:
        flat_list.append(item)

Jest szybszy niż dotychczas zamieszczone skróty. (t jest listą do spłaszczenia.)

Oto odpowiednia funkcja:

flatten = lambda t: [item for sublist in t for item in sublist]

Jako dowód możesz użyć modułu timeit w bibliotece standardowej:

$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in t for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(t, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,t)'
1000 loops, best of 3: 1.1 msec per loop

Wyjaśnienie: skróty oparte na + (w tym domyślne użycie w sum) są, z konieczności, O(T**2), gdy istnieją podlisty T - ponieważ lista wyników pośrednich wciąż się co więcej, przy każdym kroku przydziela się nowy obiekt pośredniej listy wyników, a wszystkie elementy z poprzedniego wyniku pośredniego muszą zostać skopiowane (a także kilka nowych dodanych na końcu). Tak więc, dla uproszczenia i bez faktycznej utraty ogólności, powiedzmy, że masz t sublisty elementów k każdy: pierwsze elementy k są kopiowane tam iz powrotem t-1 razy, drugie elementy k T-2 razy, i tak dalej; całkowita liczba kopii to K razy suma x dla X od 1 do T wykluczone, tj. k * (T**2)/2.

The list comprehension generuje tylko jedną listę, raz, i kopiuje każdy element (z pierwotnego miejsca zamieszkania do listy wynikowej) również dokładnie raz.

 5511
Author: Alex Martelli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2021-01-06 23:17:03

Możesz użyć itertools.chain():

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

Lub możesz użyć itertools.chain.from_iterable() który nie wymaga rozpakowywania listy z * operator :

import itertools
list2d = [[1,2,3], [4,5,6], [7], [8,9]]
merged = list(itertools.chain.from_iterable(list2d))
 1758
Author: Shawn Chin,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-03-24 18:56:59

Notatka od autora: to jest nieefektywne. Ale fajnie, bo monoidy są zajebiste. Nie nadaje się do produkcji kodu Pythona.

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

To tylko sumuje elementy iterable przekazane w pierwszym argumencie, traktując drugi argument jako wartość początkową sumy (jeśli nie podano, 0 jest używany zamiast tego i w tym przypadku pojawi się błąd).

Ponieważ sumujesz listy zagnieżdżone, otrzymujesz [1,3]+[2,4] w wyniku sum([[1,3],[2,4]],[]), który jest równy [1,3,2,4].

Zauważ, że działa tylko na listach list. W przypadku List List, będziesz potrzebował innego rozwiązania.

 1003
Author: Triptych,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-29 16:00:39

Przetestowałem większość proponowanych rozwiązań z perfplot (mój projekt pet, zasadniczo owijka wokół timeit) i znalazłem

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

Być najszybszym rozwiązaniem, zarówno gdy wiele małych list, jak i kilka długich list są połączone. (operator.iadd jest równie szybki.)

Tutaj wpisz opis obrazka

Tutaj wpisz opis obrazka


Kod do odtworzenia fabuły:

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,
    # setup=lambda n: [list(range(n))] * 10,
    kernels=[
        forfor,
        sum_brackets,
        functools_reduce,
        functools_reduce_iconcat,
        itertools_chain,
        numpy_flat,
        numpy_concatenate,
    ],
    n_range=[2 ** k for k in range(16)],
    xlabel="num lists (of length 10)",
    # xlabel="len lists (10 lists total)"
)
 595
Author: Nico Schlömer,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-11-05 01:23:14
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]

Metoda extend() w twoim przykładzie modyfikuje x zamiast zwracać użyteczną wartość (której reduce() oczekuje).

Szybszym sposobem wykonania reduce będzie

>>> 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]
 216
Author: Greg Hewgill,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-01-02 05:02:41

Nie odkrywaj koła, jeśli używasz Django :

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

...Pandy :

>>> 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))
 205
Author: Max Malysh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-04-01 14:10:58

Oto ogólne podejście, które stosuje się do liczb, struny, zagnieżdżone listy i mieszane kontenery.

Kod

#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

uwagi:

Demo

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']

Numer referencyjny

  • To rozwiązanie jest zmodyfikowany z przepisu w Beazley, D. and B. Jones. Recipe 4.14, Python Cookbook 3rd Ed., O ' Reilly Media Inc.
  • znalazłem wcześniejszy więc post , prawdopodobnie oryginalna demonstracja.
 131
Author: pylang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-06-12 23:16:42

Jeśli chcesz spłaszczyć strukturę danych, w której nie wiesz, jak głęboka jest zagnieżdżona, możesz użyć 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]

Jest to generator, więc musisz oddać wynik do list lub jawnie iterować nad nim.


Aby spłaszczyć tylko jeden poziom i jeśli każdy z przedmiotów jest iterable można również użyć iteration_utilities.flatten który sam w sobie jest tylko cienkim opakowaniem wokół 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]

Aby dodać kilka timingów (na podstawie Nico Odpowiedź schlömera, która nie zawierała funkcji przedstawionej w tej odpowiedzi):

Tutaj wpisz opis obrazka

Jest to Wykres log-log dla ogromnego zakresu wartości. Dla rozumowania jakościowego: niższe jest lepsze.

Wyniki pokazują, że jeśli iterable zawiera tylko kilka wewnętrznych iterabli, to {[7] } będzie najszybszy, jednak dla długich iterabli tylko itertools.chain.from_iterable, iteration_utilities.deepflatten lub zagnieżdżone zrozumienie mają rozsądną wydajność z itertools.chain.from_iterable jest najszybszy (jak już zauważony przez Nico Schlömera).

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 Uwaga: jestem autorem tej biblioteki

 60
Author: MSeifert,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-04-18 21:27:43

Cofam swoje zeznanie. sum nie jest zwycięzcą. Chociaż jest to szybsze, gdy lista jest mała. Ale wydajność znacznie się pogarsza przy większych listach.

>>> 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

Wersja sum nadal działa przez ponad minutę i nie została jeszcze przetworzona!

Dla list średnich:

>>> 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

Using small lists and timeit: 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
 45
Author: Nadia Alramli,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2013-12-23 09:14:58

Wydaje się być zamieszanie z operator.add! Gdy dodasz dwie listy razem, poprawnym terminem na to jest concat, a nie Dodaj. operator.concat jest tym, czego potrzebujesz.

Jeśli myślisz o funkcjonalności, to jest tak proste jak to::

>>> 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)

Widzisz redukcję typu sekwencji, więc kiedy podasz krotkę, otrzymasz z powrotem krotkę. Spróbujmy z listą::

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

A co z wydajnością::

>>> 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 jest dość szybki! Ale to nie porównanie do redukcji z 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
 43
Author: Meitham,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-05-09 04:33:26

Dlaczego używasz extend?

reduce(lambda x, y: x+y, l)
To powinno zadziałać.
 39
Author: Andrea Ambu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2014-12-31 12:07:09

Rozważ instalację more_itertools paczka.

> pip install more_itertools
[[7]}to statek z implementacją dla flatten (źródło , z receptur 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]

Uwaga: Jak wspomniano w docs, flatten wymaga listy list. Patrz poniżej na spłaszczenie bardziej nieregularnych wejść.


Od wersji 2.4 można spłaszczyć bardziej skomplikowane, zagnieżdżone iteraby za pomocą more_itertools.collapse (źródło , dodane przez 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]
 37
Author: pylang,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-09-08 19:44:09

Powodem, dla którego twoja funkcja nie działała, jest to, że extend rozszerza tablicę w miejscu i nie zwraca jej. Nadal możesz zwrócić x z lambda, używając czegoś takiego:

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

Uwaga: extend jest bardziej wydajny niż + na listach.

 28
Author: Igor Krivokon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-11-19 16:26:36
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]
 22
Author: Anil,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-28 08:48:33

Wersja rekurencyjna

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]
 21
Author: Saurabh Singh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-12-14 10:51:18

Złą cechą powyższej funkcji Anil jest to, że wymaga ona od użytkownika ręcznego podania drugiego argumentu jako pustej listy []. Powinno to być domyślne. Ze względu na sposób działania obiektów Pythona, powinny one być ustawiane wewnątrz funkcji, a nie w argumentach.

Oto działająca funkcja:

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

Testowanie:

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]
 21
Author: CoderGuy123,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-06-10 17:18:55

Zaakceptowana odpowiedź nie sprawdziła się dla mnie w przypadku list tekstowych o zmiennej długości. Oto alternatywne podejście, które zadziałało dla mnie.

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

Zaakceptowana odpowiedź, która nie zadziałała , a nie:

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']

Nowe proponowane rozwiązanie, którezadziałało dla mnie:

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']
 20
Author: user9074332,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-10-12 01:32:31

matplotlib.cbook.flatten() będzie działać dla zagnieżdżonych list, nawet jeśli zagnieżdżą się głębiej niż w przykładzie.

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))

Wynik:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
To jest 18x szybsze niż podkreślenie._."flatten": {]}
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
 17
Author: EL_DON,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-20 18:16:43

Następujące wydają mi się najprostsze:

>>> 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]
 16
Author: devil in the detail,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-07-05 05:14:38

Można również użyć NumPy ' S flat :

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

Edycja 11/02/2016: działa tylko wtedy, gdy podlisty mają identyczne wymiary.

 13
Author: mdh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-02 09:59:40
from nltk import flatten

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

Zaletą tego rozwiązania w stosunku do większości innych jest to, że jeśli masz listę taką jak:

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

Podczas gdy większość innych rozwiązań powoduje błąd, To rozwiązanie je obsługuje.

 8
Author: Alijy,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2019-09-30 10:49:25

Osobiście trudno mi zapamiętać wszystkie moduły, które musiały zostać zaimportowane. Dlatego mam tendencję do korzystania z prostej metody, chociaż Nie wiem, jak jej wydajność jest w porównaniu z innymi odpowiedziami.

Jeśli chcesz tylko spłaszczyć zagnieżdżone listy, wykonasz następujące zadanie:

def flatten(lst):
    for item in lst:
        if isinstance(item, list):
            yield from flatten(item)
        else:
            yield item

# test case:
a =[0, [], "fun", [1, 2, 3], [4, [5], 6], 3, [7], [8, 9]]
list(flatten(a))
# output 
# [0, 'fun', 1, 2, 3, 4, 5, 6, 3, 7, 8, 9]

Jeśli jednak chcesz spłaszczyć listę iterables( lista i / lub krotki), może również wykonać zadanie z niewielką modyfikacją:

from collections.abc import Iterable
def flatten(lst):
    for item in lst:
        if isinstance(item,Iterable) and not isinstance(item,str):
            yield from flatten(item)
        else:
            yield item

# test case:
a =[0, [], "fun", (1, 2, 3), [4, [5], (6)], 3, [7], [8, 9]]
list(flatten(a))
# output: 
# [0, 'fun', 1, 2, 3, 4, 5, 6, 3, 7, 8, 9]
 8
Author: Albert G Lieu,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2020-12-25 06:49:18

Uwaga: Poniżej dotyczy Pythona 3.3+, ponieważ używa yield_from. six jest również pakietem firm trzecich, choć jest stabilny. Alternatywnie możesz użyć sys.version.


W przypadku obj = [[1, 2,], [3, 4], [5, 6]], Wszystkie rozwiązania tutaj są dobre, w tym zrozumienie listy i itertools.chain.from_iterable.

Jednak rozważ ten nieco bardziej złożony przypadek:

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

Jest tu kilka problemów:

  • jeden element, 6, jest tylko skalarem; nie jest iteracyjny, więc powyższe trasy zawiodą tutaj.
  • jeden element, 'abc', jest technicznie iterowalne (wszystkie strS są). Jednak, czytając trochę między wierszami, nie chcesz traktować go jako takiego-chcesz traktować go jako pojedynczy element.
  • ostatni element, {[10] } jest zagnieżdżonym iterowalnym. Podstawowe zrozumienie listy i chain.from_iterable tylko wyciąg "1 poziom w dół."

Możesz to naprawić w następujący sposób:

>>> 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]

Tutaj sprawdzasz, czy element podrzędny (1) jest iterowalny z Iterable, ABC z itertools, ale również chce się upewnić, że (2) element jest , a nie "podobny do łańcucha."

 7
Author: Brad Solomon,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-19 19:38:25

Możesz użyć numpy :
flat_list = list(np.concatenate(list_of_list))

 7
Author: A. Attia,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-07-24 09:11:26

Jeśli chcesz zrezygnować z niewielkiej ilości prędkości na czystszy wygląd, możesz użyć numpy.concatenate().tolist() lub 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

Możesz dowiedzieć się więcej tutaj w docs numpy.konkatenat i numpy.ravel

 6
Author: mkultra,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-10-27 03:31:54

Najszybsze rozwiązanie jakie znalazłem (w każdym razie dla dużej listy):

import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()
Zrobione! Możesz oczywiście zamienić ją z powrotem w listę, wykonując list (l)
 6
Author: Canuck,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2016-11-28 21:09:09

Prosty kod dla underscore.py pakiet wentylator

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

Rozwiązuje wszystkie problemy spłaszczania (brak pozycji listy lub złożone zagnieżdżanie)

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]

Możesz zainstalować underscore.py z pip

pip install underscore.py
 6
Author: Vu Anh,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-03-25 05:09:57
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])
 6
Author: englealuze,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2017-08-08 14:59:07

To może nie jest najskuteczniejszy sposób, ale pomyślałem, aby umieścić jednoliniowy (właściwie dwuliniowy). Obie wersje będą działać na dowolnie zagnieżdżonych listach hierarchii oraz na exploitach funkcji języka (Python3. 5) i rekurencji.

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)

Wyjście to

[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13, 14, 15, 16, 17, 18]
[[8]}to działa przede wszystkim dogłębnie. Rekurencja jest następująca, dopóki nie znajdzie elementu niebędącego listą, następnie rozszerza zmienną lokalną flist, a następnie zwraca ją do rodzica. Gdy zwracane jest flist, jest ono rozszerzane do rodzica flist na liście. Dlatego w katalogu głównym zwracana jest płaska lista.

Powyższy tworzy kilka list lokalnych i zwraca je, które są używane do rozszerzenia listy rodzica. Myślę, że sposobem na to może być stworzenie gloabl flist, Jak Poniżej.

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)

Wyjście jest ponownie

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

Chociaż nie jestem pewien w tej chwili co do skuteczności.

 6
Author: phoxis,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-05-20 08:47:32
flat_list = []
for i in list_of_list:
    flat_list+=i

Ten kod działa również dobrze, ponieważ po prostu rozszerza listę do końca. Chociaż jest bardzo podobny, ale tylko jeden dla pętli. Ma więc mniejszą złożoność niż dodawanie 2 dla pętli.

 6
Author: Deepak Yadav,
Warning: date(): Invalid date.timezone value 'Europe/Kyiv', we selected the timezone 'UTC' for now. in /var/www/agent_stack/data/www/doraprojects.net/template/agent.layouts/content.php on line 54
2018-06-20 11:12:25