以此为本,以此为本,以此为本,以此为本,以此为本,以此为本,以此为本。


如果您的列表来自列表理解,问题可以通过纠正理解更简单/直接解决;请参见Python列表理解;压缩列表?

在这里,最受欢迎的解决方案通常只包含一个“层”的清单。 查看清单不规则(自愿清单)的清单,解决方案完全清单一个深度清单的结构(重复,一般)。


当前回答

注意: 下面适用于 Python 3.3+ 因为它使用 yield_from. six 也是第三方包,尽管它是稳定的。


在obj = [1, 2,], [3, 4], [5, 6]的情况下,这里的所有解决方案都很好,包括列表理解和 itertools.chain.from_iterable。

但是,考虑这个稍微复杂的案例:

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

这里有几个问题:

您可以以以下方式解决此问题:

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

在这里,您可以检查(一)的子元素(一)与(一)的Iterable(一)无效,从(一)的ABC,但也希望确保(二)的元素(一)不是“类似于(一)的”。

其他回答

要插入深厚的数据结构,请使用 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]

这是一个发电机,所以你需要将结果投到列表中,或者明确地对其进行调解。


要单一的平面,如果每一个项目本身是不可分割的,你也可以使用 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]

只需添加一些时间表(基于Nico Schlömer的答案,其中不包含此答案中的功能):

此分類上一篇

结果表明,如果 iterable 只包含几个内部 iterables 那么 总数将是最快的,但是,对于长期 iterables 只有 itertools.chain.from_iterable, iteration_utilities.deepflatten 或 nested 理解具有合理的性能, itertools.chain.from_iterable 是最快的(如 Nico Schlömer 已经注意到)。

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 Disclaimer:我是该图书馆的作者

使用 functools.reduce,将积累的列表 xs 添加到下列列表 ys:

from functools import reduce
xss = [[1,2,3], [4,5,6], [7], [8,9]]
out = reduce(lambda xs, ys: xs + ys, xss)

出口:

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

使用 operator.concat 的更快方法:

from functools import reduce
import operator
xss = [[1,2,3], [4,5,6], [7], [8,9]]
out = reduce(operator.concat, xss)

出口:

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

这对我来说似乎是最简单的:

>>> 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]
np.hstack(listoflist).tolist()

这可能不是最有效的方式,但我认为要放一个单线(实际上是一个双线)。两种版本都会在任意的序列列列表上工作,并利用语言功能(Python 3.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]

它首先以深度工作. 旋转会下降,直到它找到一个非列表元素,然后延伸当地变量板,然后转向父母。 每当板回来时,它在列表理解中延伸到父母的板。

上面的一个创建了几个地方列表,并返回它们,这些列表被用来扩展父母的列表,我认为这一点的路径可能是创建一个可怕的板块,如下。

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]

虽然我目前对效率不确定。