Создание плоского списка из списка списков в 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 списков объединяются).

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

почему вы используете extend?

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

Это должно работать нормально.


там, кажется, путаница с 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.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]

просто добавить некоторые тайминги (на основе ответа Нико Шлемера, который не включал функцию, представленную в этом ответе):

enter image description here

это лог-лог участок для размещения для огромного диапазона значений, охватываемых. Для качественного рассуждения: чем ниже, тем лучше.

результаты показывают, что если 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 строки :
flat_list = list(np.concatenate(list_of_list))


Если вы готовы отказаться от крошечного количества скорости для более чистого взгляда, то вы можете использовать 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 (все 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, Азбука из 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