Как сделать плоский список из списка списков - PullRequest
2641 голосов
/ 05 июня 2009

Интересно, есть ли ярлык для создания простого списка из списка списков в 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'

Ответы [ 39 ]

2 голосов
/ 31 января 2018

Это можно сделать с помощью toolz.concat или cytoolz.concat (версия с цитонизацией, которая в некоторых случаях может быть быстрее):

from cytoolz import concat
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(concat(l)) # or just `concat(l)` if one only wants to iterate over the items

На моем компьютере, в python 3.6, это время кажется почти таким же быстрым, как [item for sublist in l for item in sublist] (не считая времени импорта):

In [611]: %timeit L = [item for sublist in l for item in sublist]
695 ns ± 2.75 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [612]: %timeit L = [item for sublist in l for item in sublist]
701 ns ± 5.5 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [613]: %timeit L = list(concat(l))
719 ns ± 12 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [614]: %timeit L = list(concat(l))
719 ns ± 22.9 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

Версия toolz действительно медленнее:

In [618]: from toolz import concat

In [619]: %timeit L = list(concat(l))
845 ns ± 29 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)

In [620]: %timeit L = list(concat(l))
833 ns ± 8.73 ns per loop (mean ± std. dev. of 7 runs, 1000000 loops each)
2 голосов
/ 19 октября 2017

Вы можете избежать рекурсивных вызовов в стек, просто используя реальную структуру данных стека.

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)))
1 голос
/ 15 апреля 2019

Кидаю шляпу в кольцо ...

B = [ [...], [...], ... ]
A = []
for i in B:
  A.extend(i)
1 голос
/ 13 апреля 2019

Вы можете использовать Dask, чтобы сгладить / объединить список, с дополнительным преимуществом сохранения памяти. Dask использует задержанную память, которая активируется только с помощью compute (). Таким образом, вы можете использовать Dask Bag API в своем списке, а затем вычислить () в конце. Документация: http://docs.dask.org/en/latest/bag-api.html

import dask.bag as db

my_list = [[1,2,3],[4,5,6],[7,8,9]]
my_list = db.from_sequence(my_list, npartitions = 1)
my_list = my_list.flatten().compute()

# [1,2,3,4,5,6,7,8,9]
1 голос
/ 02 июля 2018

Мы можем сделать то же самое в, используя основные понятия Python

nested_list=[10,20,[30,40,[50]],[80,[10,[20]],90],60]
flat_list=[]
def unpack(list1):
    for item in list1:
        try:
            len(item)
            unpack(item)
        except:
            flat_list.append(item)
unpack(nested_list)
print (flat_list)
0 голосов
/ 20 мая 2019

Мое решение (интуитивно понятное и короткое):

def unnest(lists):
    unnested = []
    for l in lists:
        unnested = unnested + l
    return unnested
0 голосов
/ 22 марта 2017

Пример очистки @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

0 голосов
/ 28 ноября 2018

Это работает с произвольно вложенными списками. Его можно легко расширить для работы с другими типами итераций.

def flatten(seq):
    """list -> list                                                                                                                                                                           
    return a flattend list from an abitrarily nested list                                                                                                                                     
    """
    if not seq:
        return seq
    if not isinstance(seq[0], list):
        return [seq[0]] + flatten(seq[1:])
    return flatten(seq[0]) + flatten(seq[1:])

Пробный прогон

>>> flatten([1, [2, 3], [[[4, 5, 6], 7], [[8]]], 9])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
0 голосов
/ 16 марта 2018

Я думаю, что самый простой и универсальный способ - написать рекурсивную функцию следующим образом:

def flat_list(some_list = []):
elements=[]
for item in some_list:
    if type(item) == type([]):
        elements += flat_list(item)
    else:
        elements.append(item)
return elements

list =  ['a', 'b', 1, 2, 3, [1, 2, 3, 'c',[112,123,111,[1234,1111,3333,44444]]]]
flat_list(list)

>>> ['a', 'b', 1, 2, 3, 1, 2, 3, 'c', 112, 123, 111, 1234, 1111, 3333, 44444]

1007 *

...