Создание плоского списка из списка списков в Python
интересно, есть ли ярлык для сделать простой список из списка списков в Python.
Я могу сделать это в цикле 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'
30 ответов
flat_list = [item for sublist in l for item in sublist]
что означает:
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 подсписок -- как список промежуточных результатов становится все длиннее, на каждом шаге выделяется новый объект списка промежуточных результатов, и все элементы в предыдущем промежуточном результате должны быть скопированы (а также несколько новых, добавленных в конце). Итак (для простоты и без фактической потери общности) скажем, что у вас есть L подсписков I элементов каждый: первые I элементы копируются назад и вперед L-1 раз, вторые I элементы L-2 раза и так далее; Общее количество копий I раз сумма 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
Примечание автора: это неэффективно. Но весело, потому что монады потрясающие. Это не подходит для производственного кода Python.
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Это просто суммирует элементы iterable, переданные в первом аргументе, рассматривая второй аргумент как начальное значение суммы (если не задано, , и этот случай даст вам ошибку).
поскольку вы суммируете вложенные списки, вы фактически получаете [1,3]+[2,4]
в результате sum([[1,3],[2,4]],[])
, что равно [1,3,2,4]
.
обратите внимание, что работает только на списки списки. Для списков списков списков вам понадобится другое решение.
я протестировал большинство предлагаемых решений с perfplot (мой любимый проект, по сути, обертка вокруг timeit
), и нашли
list(itertools.chain.from_iterable(a))
чтобы быть самым быстрым решением (если более 10 списков объединяются).
код для воспроизведения сюжета:
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'
)
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 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
Примечание: в Python 3, yield from flatten(x)
заменить for sub_x in flatten(x): yield sub_x
демо
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']
ссылка
- это решение модифицируется из рецепта в Бизли, Д. и Б. Джонс. Рецепт 4.14, питона кулинарную книгу 3-е изд., O'Reilly Media Inc. Севастополь, ca: 2013.
- нашел ранее так пост, возможно, оригинальная демонстрация.
беру свои показания обратно. сумма не является победителем. Хотя это быстрее, когда список невелик. Но производительность значительно ухудшается с большими списками.
>>> 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
использование небольших списков и 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
там, кажется, путаница с operator.add
! Когда вы добавляете два списка вместе, правильным термином для этого является concat
не добавлять. operator.concat
это то, что вам нужно использовать.
если вы думаете функционально, это так же просто, как это::
>>> list2d = ((1, 2, 3), (4, 5, 6), (7,), (8, 9))
>>> reduce(operator.concat, list2d)
(1, 2, 3, 4, 5, 6, 7, 8, 9)
вы видите, что 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]]
>>> %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
если вы хотите сгладить структуру данных, где вы не знаете, насколько глубоко она вложена, вы можете использовать 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]
это генератор, поэтому вам нужно привести результат к 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]
просто добавить некоторые тайминги (на основе ответа Нико Шлемера, который не включал функцию, представленную в этом ответе):
это лог-лог участок для размещения для огромного диапазона значений, охватываемых. Для качественного рассуждения: чем ниже, тем лучше.
результаты показывают, что если iterable содержит только несколько внутренних iterables, то sum
будет самым быстрым, однако для длинных итераций только itertools.chain.from_iterable
, iteration_utilities.deepflatten
или вложенное понимание имеет разумную производительность с itertools.chain.from_iterable
быть самым быстрым (как уже заметил Нико Шлемер).
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 Отказ от ответственности: я автор этой библиотеки
установите 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]
причина, по которой ваша функция не работала: расширение расширяет массив на месте и не возвращает его. Вы все еще можете вернуть x из лямбды, используя какой-то трюк:
reduce(lambda x,y: x.extend(y) or x, l)
Примечание: расширение более эффективно, чем + в списках.
плохая особенность функции Анила выше заключается в том, что она требует от пользователя всегда вручную указывать второй аргумент, чтобы быть пустым списком []
. Это должно быть по умолчанию. Из-за того, как работают объекты Python, они должны быть установлены внутри функции, а не в аргументах.
вот рабочая функция:
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]
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]
следующее кажется мне самым простым:
>>> 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 это квартира:
import numpy as np
list(np.array(l).flat)
Edit 11/02/2016: работает только тогда, когда подсписки имеют одинаковые размеры.
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]
это 18x быстрее, чем подчеркивание._.сплющить:
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
простой код 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:])
Если вы готовы отказаться от крошечного количества скорости для более чистого взгляда, то вы можете использовать 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.конкатенат и и NumPy.Равель!--7-->
flat_list = []
for i in list_of_list:
flat_list+=i
этот код также отлично работает, так как он просто расширяет список полностью. Хотя он очень похож, но имеет только один цикл for. Таким образом, он имеет меньшую сложность, чем добавление 2 для циклов.
самое быстрое решение, которое я нашел (для большого списка в любом случае):
import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()
готово! Конечно, вы можете превратить его обратно в список, выполнив list (l)
Я недавно наткнулся на ситуацию, когда у меня была смесь из строк и числовых данных в подсписки, например
test = ['591212948',
['special', 'assoc', 'of', 'Chicago', 'Jon', 'Doe'],
['Jon'],
['Doe'],
['fl'],
92001,
555555555,
'hello',
['hello2', 'a'],
'b',
['hello33', ['z', 'w'], 'b']]
где методы, такие как flat_list = [item for sublist in test for item in sublist]
не работал. Итак, я придумал следующее решение для 1 + уровня подсписков
def concatList(data):
results = []
for rec in data:
if type(rec) == list:
results += rec
results = concatList(results)
else:
results.append(rec)
return results
и в результате
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']
еще один необычный подход, который работает для гетеро - и гомогенных списков целых чисел:
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(',')]
принятый ответ не работа для меня при работе с текстовыми списками переменной длины. Вот альтернативный подход, который сработал для меня.
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']
вы можете избежать рекурсивных вызовов стека, используя фактическую структуру данных стека довольно просто.
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)))
это может быть не самый эффективный способ, но я думал поставить один лайнер (на самом деле два лайнера). Обе версии будут работать с вложенными списками произвольной иерархии и использовать языковые функции (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
, это просто скаляр, это не Iterable, так что вышеперечисленные маршруты будут не здесь. - один элемент
'abc'
, is технически iterable (всеstr
s являются). Однако, читая между строк, вы не хотите рассматривать это как таковое-вы хотите рассматривать это как один элемент. - конечный элемент
[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
, Азбука из itertools
, но также хотите убедиться ,что (2) Элемент не "струна-как."
очищен @ Deleet пример
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))
пример:https://repl.it/G8mb/0