如何从列表列表中制作一个平面列表

时间:2009-06-04 20:30:06

标签: python list multidimensional-array flatten

我想知道是否有一条快捷方式可以在Python列表中列出一个简单的列表。

我可以在for循环中执行此操作,但也许有一些很酷的“单行”?我尝试使用 reduce ,但是我收到了错误。

代码

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'

64 个答案:

答案 0 :(得分:3781)

给出列表l

flat_list = [item for sublist in l for item in sublist]

表示:

flat_list = []
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

说明:当有L个子列表时,基于+的快捷方式(包括sum中隐含的用法)必然为O(L**2) - 因为中间结果列表不断获取更长的时候,每个步骤都会分配一个新的中间结果列表对象,并且必须复制前一个中间结果中的所有项目(以及最后添加的一些新项目)。因此,为了简单而没有实际失去一般性,请说每个项目都有L个子列表:第一个I项目来回复制L-1次,第二个I项目L-2次,依此类推;总复制数是I乘以x的总和,从1到L排除,即I * (L**2)/2

列表理解只生成一个列表一次,并将每个项目(从其原始居住地点到结果列表)复制一次。

答案 1 :(得分:1277)

您可以使用itertools.chain()

>>> import itertools
>>> list2d = [[1,2,3],[4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))

或者,在Python&gt; = 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

答案 2 :(得分:746)

作者注意:效率低下。但很有趣,因为monoids非常棒。它不适合生产Python代码。

>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]

这只是对第一个参数中传递的iterable元素进行求和,将第二个参数视为总和的初始值(如果没有给出,则使用0代替,这种情况会给你一个错误)。 / p>

由于您要对嵌套列表求和,因此[1,3]+[2,4]实际上得到的sum([[1,3],[2,4]],[])等于[1,3,2,4]

请注意,仅适用于列表列表。对于列表列表,您需要另一种解决方案。

答案 3 :(得分:266)

我使用perfplot(我的宠物项目,基本上是# Set effective dates for tasks set -A EDATE `sqlplus -s / << ENDSQL set pages 0 feed off set timing off alter session set nls_date_format='DD-MM-YYYY'; select sysdate + 42, sysdate + 51, sysdate + 50 from dual; ENDSQL` # Check effective dates set # ${EDATE[0]} = SYSDATE + 42 for tasks NORMALISED # ${EDATE[1]} = SYSDATE + 51 for tasks SUBTOTAL, SUBTOTAL_RAT # ${EDATE[2]} = SYSDATE + 50 for tasks NORMALISED_EV,CHARGE typeset -i C=0 while [[ $C -lt 3 ]] ; do if [[ -z "${EDATE[C]}" ]] ; then echo "FAILED TO SET ROTATE PARTITION TASKS EFFECTIVE DATE! PLEASE CHECK." sms "${SV_SL}" "Failed to set Rotate Partition Tasks effective date. Please check." exit -1 fi let C+=1 done 的包装)测试了大多数建议的解决方案,并找到了

timeit

是最快的解决方案。 (functools.reduce(operator.iconcat, a, []) 同样快。)

enter image description here

重现情节的代码:

operator.iadd

答案 4 :(得分:134)

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]

答案 5 :(得分:78)

以下是适用于数字字符串嵌套列表和混合容器的一般方法。< / p>

<强>代码

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

<强>参考

  • 此解决方案是根据 Beazley,D。和B. Jones的配方修改的。食谱4.14,Python Cookbook 3rd Ed。,O'Reilly Media Inc. Sebastopol,CA:2013。
  • 找到较早的SO post,可能是最初的演示。

答案 6 :(得分:37)

我接受我的陈述。总和不是赢家。虽然列表很小但速度更快。但是,较大的列表会使性能显着下降。

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

总和版本仍在运行超过一分钟,尚未完成处理!

对于中型名单:

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

使用小名单和时间:数字= 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

答案 7 :(得分:37)

如果你想展平一个数据结构,你不知道它嵌套的深度,你可以使用iteration_utilities.deepflatten 1

o=TUDelft, c=NL

它是一个生成器,因此您需要将结果转换为>>> 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.flattenitertools.chain.from_iterable本身只是enter image description here的一个薄包装:

list

只是添加一些时间(基于NicoSchlömer的答案,不包括此答案中提供的功能):

{{3}}

这是一个对数日志图,可以适应大范围的跨越值。对于定性推理:越低越好。

结果显示,如果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] 将是最快的,但对于长迭代,只有sumitertools.chain.from_iterable或嵌套理解具有合理的性能iteration_utilities.deepflatten是最快的(正如NicoSchlömer已经注意到的那样)。

itertools.chain.from_iterable

1免责声明:我是该图书馆的作者

答案 8 :(得分:31)

似乎与667869 667869 580083 580083 316133 316133 9020 9020 混淆了!当您将两个列表一起添加时,正确的术语是operator.add,而不是添加。 concat是你需要使用的。

如果您正在考虑功能,那就像这个一样简单:

operator.concat

你看到reduce尊重序列类型,所以当你提供一个元组时,你会得到一个元组。让我们尝试使用list ::

>>> from functools import 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]]
>>> 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

答案 9 :(得分:30)

为什么使用extend?

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

这应该可以正常工作。

答案 10 :(得分:19)

考虑安装more_itertools包。

> pip install more_itertools

它附带flatten sourceitertools recipes实施内容:

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.collapsesource(由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]

答案 11 :(得分:18)

您的函数不起作用的原因:extend将数组扩展到原位并且不返回它。您仍然可以使用一些技巧从lambda返回x:

reduce(lambda x,y: x.extend(y) or x, l)

注意:extend比列表上的+更有效。

答案 12 :(得分:13)

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]

答案 13 :(得分:12)

上面Anil函数的一个不好的功能是它要求用户始终手动指定第二个参数为空列表[]。这应该是默认值。由于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]

答案 14 :(得分:11)

在处理基于文本的可变长度列表时,可接受的答案对我不起作用。这是对我有用的另一种方法。

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

答案 15 :(得分:10)

matplotlib.cbook.flatten() will work for nested lists even if they nest more deeply than the example.

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

Result:

[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]

This is 18x faster than underscore._.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

答案 16 :(得分: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]

答案 17 :(得分:8)

也可以使用NumPy的flat

import numpy as np
list(np.array(l).flat)

编辑11/02/2016:仅在子列表具有相同尺寸时才有效。

答案 18 :(得分:8)

这是对原始海报代码的播放。 (他就在不远处)

f = []
list(map(f.extend, l))

答案 19 :(得分:6)

您可以使用numpy:
flat_list = list(np.concatenate(list_of_list))

答案 20 :(得分:6)

递归版本

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

def flatten_list(k):
    result = list()
    for i in k:
        if isinstance(i,list):

            #The isinstance() function checks if the object (first argument) is an 
            #instance or subclass of classinfo class (second argument)

            result.extend(flatten_list(i)) #Recursive call
        else:
            result.append(i)
    return result

flatten_list(x)
#result = [1,2,3,4,5,6,7,8,9,10]

答案 21 :(得分:5)

另一种适用于异构和同类整数列表的不寻常方法:

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(',')]

答案 22 :(得分:5)

flat_list = []
for i in list_of_list:
    flat_list+=i

此代码也可以很好地工作,因为它可以一直扩展列表。虽然非常相似,但是只有一个for循环。因此,它比添加2 for循环的复杂度要低。

答案 23 :(得分:5)

def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])

答案 24 :(得分:5)

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]

您可以使用pip

安装underscore.py
pip install underscore.py

答案 25 :(得分:5)

from nltk import flatten

l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
flatten(l)

此解决方案相对于大多数其他解决方案的优势在于,如果您有类似以下的列表:

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

大多数其他解决方案都会引发错误,而该解决方案会处理它们。

答案 26 :(得分:5)

您可以使用list extend方法,它显示出最快的速度:

flat_list = []
for sublist in l:
    flat_list.extend(sublist)

效果:

import functools
import itertools
import numpy
import operator
import perfplot



def functools_reduce_iconcat(a):
    return functools.reduce(operator.iconcat, a, [])


def itertools_chain(a):
    return list(itertools.chain.from_iterable(a))


def numpy_flat(a):
    return list(numpy.array(a).flat)


def extend(a):
    n = []

    list(map(n.extend, a))

    return n 


perfplot.show(
    setup=lambda n: [list(range(10))] * n,
    kernels=[
        functools_reduce_iconcat, extend,itertools_chain, numpy_flat
        ],
    n_range=[2**k for k in range(16)],
    xlabel='num lists',
    )

输出enter image description here

答案 27 :(得分:4)

使用reduce中的functools和列表中的add运算符的简单递归方法:

>>> from functools import reduce
>>> from operator import add
>>> flatten = lambda lst: [lst] if type(lst) is int else reduce(add, [flatten(ele) for ele in lst])
>>> flatten(l)
[1, 2, 3, 4, 5, 6, 7, 8, 9]

函数flattenlst作为参数。它循环lst的所有元素,直到达到整数为止(对于其他数据类型,也可以将int更改为floatstr等),并添加到返回值中最外层递归的值。

for循环和monad之类的方法不同,递归是一种不受列表深度限制的通用解决方案。例如,深度为5的列表可以用与l相同的方式展平:

>>> l2 = [[3, [1, 2], [[[6], 5], 4, 0], 7, [[8]], [9, 10]]]
>>> flatten(l2)
[3, 1, 2, 6, 5, 4, 0, 7, 8, 9, 10]

答案 28 :(得分:4)

这可能不是最有效的方式,但我想放一个单线(实际上是一个双线)。这两个版本都可以在任意层次结构嵌套列表上运行,并利用语言功能(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。因此,在根目录下,将返回一个平面列表。

上面的列表创建了几个本地列表并返回它们,这些列表用于扩展父列表。我认为解决这个问题的方法可能是创建一个全球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]

虽然目前我不确定效率。

答案 29 :(得分:4)

Note: Below applies to Python 3.3+ because it uses yield_from. six is also a third-party package, though it is stable. Alternately, you could use sys.version.


In the case of obj = [[1, 2,], [3, 4], [5, 6]], all of the solutions here are good, including list comprehension and itertools.chain.from_iterable.

However, consider this slightly more complex case:

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

There are several problems here:

  • One element, 6, is just a scalar; it's not iterable, so the above routes will fail here.
  • One element, 'abc', is technically iterable (all strs are). However, reading between the lines a bit, you don't want to treat it as such--you want to treat it as a single element.
  • The final element, [8, [9, 10]] is itself a nested iterable. Basic list comprehension and chain.from_iterable only extract "1 level down."

You can remedy this as follows:

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

Here, you check that the sub-element (1) is iterable with Iterable, an ABC from itertools, but also want to ensure that (2) the element is not "string-like."

答案 30 :(得分:3)

我最近遇到过一种情况,即我在

等子列表中混合了字符串和数字数据
function move(value, positionChange) {
  // On run, move the object in the array up or down respectivly.
  for (var i = 0; i < obj.length; i++) {
    if (obj[i].RuleDetailID == positionChange) {
      var newIndex = value === 'up' ? i - 1 : i + 1;
      if (newIndex >= obj.length || newIndex < 0) return;
      var temp = obj[i];
      obj[i] = obj[newIndex];
      obj[newIndex] = temp;
      document.getElementById('example').innerHTML = renderExample();
    }
  }
}

test = ['591212948', ['special', 'assoc', 'of', 'Chicago', 'Jon', 'Doe'], ['Jon'], ['Doe'], ['fl'], 92001, 555555555, 'hello', ['hello2', 'a'], 'b', ['hello33', ['z', 'w'], 'b']] 等方法无效。所以,我想出了以下1+级子列表的解决方案

flat_list = [item for sublist in test for item in sublist]

结果

def concatList(data):
    results = []
    for rec in data:
        if type(rec) == list:
            results += rec
            results = concatList(results)
        else:
            results.append(rec)
    return results

答案 31 :(得分:3)

我找到的最快的解决方案(无论如何都是大型列表):

import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()

完成!您当然可以通过执行list(l)

将其重新转换为列表

答案 32 :(得分:3)

如果您愿意放弃一点速度以获得更干净的外观,那么您可以使用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.concatenatenumpy.ravel

中找到更多信息

答案 33 :(得分:3)

另一种有趣的方法:

from functools import reduce
from operator import add

li=[[1,2],[3,4]]
x= reduce(add, li)

答案 34 :(得分:2)

有几个答案具有与下面相同的递归追加方案,但是没有一个答案使用try,这使解决方案更加健壮和 pythonic 。此解决方案的其他优点是:

  • 可与任何可迭代的(甚至将来的)兼容
  • 可与嵌套的任何组合和深度一起使用
  • 没有依赖项

def flatten(itr):
    t = tuple()
    for e in itr:
        try:
            t += flatten(e)
        except:
            t += (e,)
    return t

具有相同功能的另一个变体:

def flatten(itr):
    try:
        t = sum((flatten(e) for e in itr), tuple())
    except:
        t = (itr,)
    return t

如果您需要返回列表(速度稍慢),请使用list()代替tuple(),并使用[ ]代替( ,)

答案 35 :(得分:2)

这可以使用toolz.concatcytoolz.concat完成(cythonized版本,在某些情况下可能更快):

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)

答案 36 :(得分:2)

您可以非常简单地使用实际的堆栈数据结构来避免对堆栈的递归调用。

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

答案 37 :(得分:2)

我个人很难记住所有需要导入的模块。因此,即使我不知道它的性能如何与其他答案相比,我还是倾向于使用一种简单的方法。

from collections.abc import Iterable
def flatten(lst):
    for item in lst:
        if isinstance(item, Iterable) and not isinstance(item, str):
            yield from flatten(item)
        else:
            yield item
test case:
          a =[0, [], "fun", [1, 2, 3], [4, 5, 6], 3, [7], [8, 9]]
          list(flatten(a))
output 
          [0, 'fun', 1, 2, 3, 4, 5, 6, 3, 7, 8, 9]

答案 38 :(得分:2)

如果您使用的是 Django ,请不要重新发明轮子:

>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]

... 熊猫

>>> from pandas.core.common import flatten
>>> list(flatten(l))

... Itertools

>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))

... Matplotlib

>>> from matplotlib.cbook import flatten
>>> list(flatten(l))

... Unipath

>>> from unipath.path import flatten
>>> list(flatten(l))

... 设置工具

>>> from setuptools.namespaces import flatten
>>> list(flatten(l))

答案 39 :(得分:1)

解决方案不应考虑只有一两个嵌套级别。嵌套级别应被视为问题的一个变量。我建议以下解决方案

a=[1,[2,3],[4,[[[5]]],6],7,[8,9,10,11,12],[13,14,[15,16,17,[18,19,20,21,22],23,24],25],26,[27,28,29],30]
print(a)
temp=a
flat_list=[]
check=True
while check==True:
    minor_check=False    # check for at least one nesting order: initial guess
    for i in range(len(temp)):
        if (isinstance(temp[i],list)):
            minor_check=True  # there is at least one nesting order deeper in the list
            for ii in range(len(temp[i])):
                flat_list.append(temp[i][ii])
        else:
            flat_list.append(temp[i])
    check=True if minor_check==True else False
    temp=flat_list
    print(temp) # print the new flat_list at after this pass
    flat_list=[]

flat_list=temp
print(flat_list)
    

我希望这会有所帮助

答案 40 :(得分:1)

有趣的解决方案?

import pandas as pd
list(pd.DataFrame({'lists':l})['lists'].explode())


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

答案 41 :(得分:1)

最简单的方法可能是连接它们:

In[2]: l1 = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
In[3]: l2 = list(np.concatenate(l1))
In[4]: l2
Out[5]: [1, 2, 3, 4, 5, 6, 7, 8, 9]

答案 42 :(得分:1)

要遍历列表列表并检索平面列表,最好的解决方案是使用递归进行迭代:

def flat_list_recursion_example(input_list, final_list):

    """    
    Retreives a flattend list from a nested one
        Args:
            input_list(list): nested list of list. Example [[0,1],[2],[3,4]]
            final_list(list): final structure.

        Returns:
            flattened list: Example [0,1,2,3,4]
    """

    if not input_list:
        return final_list

    final_list.extend(input_list[0])

    return flat_list_recursion_example(input_list[1:],final_list)

您可以将其与以下示例结合使用:

l_0 = [i for i in range(1, 660001)]
l_1 = [i for i in range(1, 660001)]
l_2 = [i for i in range(1, 660001)]
l = [l_0,l_1,l_2]

flat_list = flat_list_recursion_example(l,[])
print(len(flat_list))

我在 Jupyter notebook 中检查了这个线程中提出的许多解决方案,这是最快的一个,至少用 %timeit 测量时间

enter image description here

答案 43 :(得分:1)

把我的帽子扔进戒指...

B = [ [...], [...], ... ]
A = []
for i in B:
  A.extend(i)

答案 44 :(得分:1)

您可以使用Dask展平/合并列表,并具有节省内存的附加好处。 Dask使用延迟的内存,该内存仅通过compute()激活。因此,您可以在列表上使用Dask Bag API,然后在最后进行compute()。 文档: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]

答案 45 :(得分:1)

还有一种方法可以做到这一点:

l=[[1,2,3],[4,5,6],[7,8,9]]
from functools import reduce
k=reduce(lambda l1,l2:l1+l2,l)
print(k)

答案 46 :(得分:1)

我们可以使用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)

答案 47 :(得分:0)

我想使用 concatenate ravelnumpy 如下

import numpy as np
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]

out = np.concatenate(np.array(l)).ravel()

答案 48 :(得分:0)

Arty 对无限深度列表和其他可迭代对象的简短回答

from collections.abc import Iterable
def flatten(x):
    if isinstance(x, Iterable):
        return sum([flatten(i) for i in x], [])
    return [x]

flatten( [[3, 4], [[5, 6], 6]])
# output [3, 4, 5, 6, 6]

答案 49 :(得分:0)

我必须创建一个列表,然后将子查询项添加到列表中,谢谢。

  l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
  l2=[]
  [[l2.append(i) for i in sublist] for sublist in l]
  print(l2)

答案 50 :(得分:0)

您可以按如下方式展平任何列表:

def make_1d(l):
    
    if not isinstance(l, list):
        return [l]

    if len(l) == 1: return make_1d(l[0])
    
    return make_1d(l[0]) + make_1d(l[1:])

让我们测试您的问题:

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

make_1d(l)
>> [1, 2, 3, 4, 5, 6, 7, 8, 9]

答案 51 :(得分:0)

尽管最初的问题中没有问过,但是如果有列表列表的列表,还有几次扁平化的兴趣...

最多也要进行depth次取消嵌套。或全部展平(当depthNone时),即将任何嵌套深度转换为一个全局展平列表,与无限depth相同。

并支持深度不同的列表嵌套。

在我的下一个递归flatten(l, depth)函数和下面的示例中实现的所有操作均不依赖于任何模块导入,并且可以偷懒地工作(发出迭代器):

Try it online!

def flatten(l, depth = 1):
    done, ndepth = False, None
    if depth is not None:
        done, ndepth = depth <= 0, depth - 1
    if not isinstance(l, list):
        l, done = [l], True
    return iter(l) if done else (e1 for e0 in l for e1 in flatten(e0, ndepth))

l = [ [ [1, [2], 3], [4, 5] ], [ [6, 7], [8, [9, 10]] ] , ['ab', 'c'], 11, 12 ]
    
for depth in [0, 1, 2, 3, 4, None]:
    print('depth', str(depth).rjust(5), ':', list(flatten(l, depth = depth)))

输出:

depth     0 : [[[1, [2], 3], [4, 5]], [[6, 7], [8, [9, 10]]], ['ab', 'c'], 11, 12]
depth     1 : [[1, [2], 3], [4, 5], [6, 7], [8, [9, 10]], 'ab', 'c', 11, 12]
depth     2 : [1, [2], 3, 4, 5, 6, 7, 8, [9, 10], 'ab', 'c', 11, 12]
depth     3 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'ab', 'c', 11, 12]
depth     4 : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'ab', 'c', 11, 12]
depth  None : [1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 'ab', 'c', 11, 12]

答案 52 :(得分:0)

这个问题有两个要求:

  1. “从列表列表中制作一个简单列表” - 即只有一层嵌套。
    此外,每个 项目都保存在一个二级列表中。 IE。没有混合,有些直接在第一个列表中,有些在嵌套列表中。例如。他例子中的 7
    l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
    是在一个列表中,所以 [7] 不是 7
  2. 他还要求“一些很酷的单线”。

基于此,对于两级列表,无需导入任何外部包,实现此目的的最简单方法是

l2=[]
[l2.extend(i) for i in l ]   #now l2==[1, 2, 3, 4, 5, 6, 7, 8, 9]

(所有的工作都在第二行完成,所以我把它算作一行)。
这将返回一个无用列表,但 l2 将使用每个嵌套列表中的每个元素进行扩展。

如果原始列表有有时是一层,有时是两层嵌套,我们可以这样做

l = [1,2,3,[4,5],6,7,[8,9,10,11],12]
l2=[]
[l2.extend(i) if type(i)==list else l2.append(i) for i in l ] 
# now l2==[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12]

这在适当时扩展(即嵌套列表),并在不适当时追加(即未嵌套)。

对于可能存在任何未知嵌套程度的列表,最简单的选择是使用 Max Malysh 的 pandas.core.common.flatten 建议。但由于问题表明嵌套程度较低,因此以上是最简单的解决方案 - 没想到其他答案都没有提出这一点。

答案 53 :(得分:0)

一种可能性是将数组视为字符串:

elements = [[180.0, 1, 2, 3], [173.8], [164.2], [156.5], [147.2], [138.2]]
list(map(float, str(elements).replace("[", "").replace("]", "").split(",")))

答案 54 :(得分:0)

清理@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

答案 55 :(得分:0)

该问题要求一些很酷的“单线”答案。然后,这是我在普通Python中的贡献:

a = [[2,3,6],[False,'foo','bar','baz'],[3.1415],[],[0,0,'0']]
flat_a = [a[i][j] for i in range(len(a)) for j in range(len(a[i]))]
flat_a
[2, 3, 6, False, 'foo', 'bar', 'baz', 3.1415, 0, 0, '0']

答案 56 :(得分:0)

如果您打算采用较慢的(运行时间)路线,则应该比检查字符串更进一步。您可能有一个嵌套的元组列表或列表元组或某些用户定义的可迭代类型的序列。

从输入序列中获取一种类型,然后进行检查。

def iter_items(seq):
    """Yield items in a sequence."""
    input_type = type(seq)

    def items(subsequence):
        if type(subsequence) != input_type:
            yield subsequence
        else:
            for sub in subsequence:
                yield from items(sub)

    yield from items(seq)


>>> list(iter_items([(1, 2), [3, 4], "abc", [5, 6], [[[[[7]]]]]]))
[(1, 2), 3, 4, 'abc', 5, 6, 7]

答案 57 :(得分:0)

我的解决方案(直观而简短)

def unnest(lists):
    unnested = []
    for l in lists:
        unnested = unnested + l
    return unnested

答案 58 :(得分:0)

这适用于任意嵌套的列表。它可以轻松扩展以与其他类型的可迭代对象一起使用。

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]

答案 59 :(得分:-1)

我认为最简单的方法和通用是编写这样的递归函数:

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]

答案 60 :(得分:-1)

在 python 3 中,我们通过使用 + 运算符来做到这一点

IN: min([5,4,3], [6])
OUT: [6]

这给出了包含所有元素的最终列表

答案 61 :(得分:-1)

np.hstack(listoflist).tolist()

答案 62 :(得分:-1)

这是一个使用递归的函数,可在任意嵌套列表中使用。

def flatten(nested_lst):
    """ Return a list after transforming the inner lists
        so that it's a 1-D list.

    >>> flatten([[[],["a"],"a"],[["ab"],[],"abc"]])
    ['a', 'a', 'ab', 'abc']
    """
    if not isinstance(nested_lst, list):
        return(nested_lst)

    res = []
    for l in nested_lst:
        if not isinstance(l, list):
            res += [l]
        else:
            res += flatten(l)


    return(res)

>>> flatten([[[],["a"],"a"],[["ab"],[],"abc"]])
['a', 'a', 'ab', 'abc']

答案 63 :(得分:-3)

我的回答是使用递归函数可能对您有帮助。

final_list = []
input_list = [[[1,[2]],[3,5]], 0]
def flatten(input_list):
    if not isinstance(input_list, list): 
       final_list.append(input_list) 
       return
    for sub_list in input_list:
        ret = lis_print(sub_list)
flatten(input_list)
print(final_list)