Tworzenie listy płaskiej z listy list w Pythonie
Zastanawiam się, czy istnieje skrót do zrobienia prostej listy z listy list w Pythonie.
Mogę to zrobić w pętli for, 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'
30 answers
flat_list = [item for sublist in l for item in sublist]
Co oznacza:
for sublist in l:
for item in sublist:
flat_list.append(item)
Jest szybszy niż dotychczas zamieszczone skróty. (l
jest listą do spłaszczenia.)
Oto odpowiednia funkcja:
flatten = lambda l: [item for sublist in l for item in sublist]
Jako dowód, jak zawsze, możesz użyć modułu timeit
w bibliotece standardowej:
$ 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
Wyjaśnienie: skróty oparte na +
(w tym domyślne użycie w sum
) są, z konieczności, O(L**2)
, gdy istnieją podlisty L - ponieważ lista wyników pośrednich jest coraz dłuższa, na każdym kroku a nowy obiekt pośredniej listy wyników zostanie przydzielony, a wszystkie elementy z poprzedniego wyniku pośredniego muszą zostać skopiowane (jak również kilka nowych dodanych na końcu). Tak więc (dla uproszczenia i bez rzeczywistej utraty ogólności) powiedzmy, że masz l sublisty elementów I: pierwsze elementy I są kopiowane tam iz powrotem L-1 razy, drugie elementy I L - 2 razy, i tak dalej; całkowita liczba kopii to I razy suma x dla X od 1 do L wykluczone, tj. I * (L**2)/2
.
Lista generuje jedną listę, raz, i kopiuje każdy element (z jego pierwotnego miejsca zamieszkania do listy wyników) również dokładnie raz.
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-06-14 21:53:08
Możesz użyć itertools.chain()
:
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))
Lub, w Pythonie > =2.6, użyj itertools.chain.from_iterable()
co nie wymaga rozpakowywania listy:
>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain.from_iterable(list2d))
To podejście jest prawdopodobnie bardziej czytelne niż {[5] } i wydaje się być również szybsze:
[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
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-03-12 17:15:50
Notatka od autora: to jest nieefektywne. Ale fajnie, bo monady 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.
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-09 16:25:42
Przetestowałem większość proponowanych rozwiązań z perfplot (mój projekt pet, zasadniczo owijka wokół timeit
) i znalazłem
list(itertools.chain.from_iterable(a))
Być najszybszym rozwiązaniem(jeśli więcej niż 10 list jest połączonych).
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 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, itertools_chain, numpy_flat,
numpy_concatenate
],
n_range=[2**k for k in range(16)],
logx=True,
logy=True,
xlabel='num lists'
)
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-18 11:05:28
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]
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
Oto ogólne podejście, które stosuje się do liczb, struny, zagnieżdżone listy i mieszane kontenery.
Kod
from collections import Iterable
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
Uwaga: w Pythonie 3, {[2] } może zastąpić for sub_x in flatten(x): yield sub_x
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 zmodyfikowane z receptury w Beazley, D. and B. Jones. Recipe 4.14, Python Cookbook 3rd Ed., O ' Reilly Media Inc.
- znaleziono wcześniej więc post , prawdopodobnie oryginalna demonstracja.
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-26 17:00:44
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
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
Dlaczego używasz extend?
reduce(lambda x, y: x+y, l)
To powinno zadziałać.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
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::
>>> 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
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-09-30 21:28:25
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.deepflatten
1
>>> 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):
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
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
Rozważ instalację more_itertools
Paczka.
> pip install more_itertools
[[6]}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]
Od wersji 2.4 można spłaszczyć bardziej skomplikowane, zagnieżdżone iteraby za pomocą more_itertools.collapse
(Źródło , autor: 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]
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-13 21:06:00
Powód, dla którego twoja funkcja nie działała: extend rozszerza tablicę na miejscu i nie zwraca jej. Nadal możesz zwrócić x z lambda, używając jakiegoś tricka:
reduce(lambda x,y: x.extend(y) or x, l)
Uwaga: extend jest bardziej wydajny niż + na listach.
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
2009-06-04 20:47:13
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]
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-29 03:45:43
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]
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
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]
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.
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
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
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
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
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:])
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
Możesz użyć numpy :flat_list = list(np.concatenate(list_of_list))
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
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
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.
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
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)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
Ostatnio natknąłem się na sytuację, w której miałem mieszankę łańcuchów i danych liczbowych w podlistach, takich jak
test = ['591212948',
['special', 'assoc', 'of', 'Chicago', 'Jon', 'Doe'],
['Jon'],
['Doe'],
['fl'],
92001,
555555555,
'hello',
['hello2', 'a'],
'b',
['hello33', ['z', 'w'], 'b']]
Gdzie metody takie jak flat_list = [item for sublist in test for item in sublist]
nie zadziałały. Tak więc, wymyśliłem następujące rozwiązanie dla poziomu 1+ podlistów
def concatList(data):
results = []
for rec in data:
if type(rec) == list:
results += rec
results = concatList(results)
else:
results.append(rec)
return results
I wynik
In [38]: concatList(test)
Out[38]:
Out[60]:
['591212948',
'special',
'assoc',
'of',
'Chicago',
'Jon',
'Doe',
'Jon',
'Doe',
'fl',
92001,
555555555,
'hello',
'hello2',
'a',
'b',
'hello33',
'z',
'w',
'b']
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-09-21 19:54:13
Inne nietypowe podejście, które działa dla hetero-i jednorodnych list liczb całkowitych:
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(',')]
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-09-13 11:34:20
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']
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
Można w prosty sposób uniknąć rekurencyjnych wywołań stosu, używając rzeczywistej struktury danych stosu.
alist = [1,[1,2],[1,2,[4,5,6],3, "33"]]
newlist = []
while len(alist) > 0 :
templist = alist.pop()
if type(templist) == type(list()) :
while len(templist) > 0 :
temp = templist.pop()
if type(temp) == type(list()) :
for x in temp :
templist.append(x)
else :
newlist.append(temp)
else :
newlist.append(templist)
print(list(reversed(newlist)))
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-10-19 05:46:09
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.
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
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 (wszystkiestr
S 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."
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
Czyszczenie @Deleet przykład
from collections import Iterable
def flatten(l, a=[]):
for i in l:
if isinstance(i, Iterable):
flatten(i, a)
else:
a.append(i)
return a
daList = [[1,4],[5,6],[23,22,234,2],[2], [ [[1,2],[1,2]],[[11,2],[11,22]] ] ]
print(flatten(daList))
Przykład: https://repl.it/G8mb/0
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-22 17:01:57