Warning: file_get_contents(/data/phpspider/zhask/data//catemap/1/list/4.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Python 如何从列表列表中生成一个简单的列表?_Python_List_Multidimensional Array_Flatten - Fatal编程技术网

Python 如何从列表列表中生成一个简单的列表?

Python 如何从列表列表中生成一个简单的列表?,python,list,multidimensional-array,flatten,Python,List,Multidimensional Array,Flatten,在Python中,有没有一种快捷方式可以从列表列表中生成一个简单的列表 我可以在for循环中完成,但可能有一些很酷的“一行程序”?我用functools.reduce() 但我得到了这个错误: 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 文件“”,第1行,在 AttributeError:“非类型”对象没有属性“扩展” 示例中的extend()方法修改x,而不是返回一个有用的值(期望) 执行reduce版本的更快方法是 >>> import operator >

在Python中,有没有一种快捷方式可以从列表列表中生成一个简单的列表

我可以在
for
循环中完成,但可能有一些很酷的“一行程序”?我用
functools.reduce()

但我得到了这个错误:

回溯(最近一次呼叫最后一次):
文件“”,第1行,在
文件“”,第1行,在
AttributeError:“非类型”对象没有属性“扩展”
示例中的
extend()
方法修改
x
,而不是返回一个有用的值(期望)

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

作者的注释:这是低效的。但是很有趣,因为你很棒。它不适用于生产Python代码

>>> l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
这只是对在第一个参数中传递的iterable的元素求和,将第二个参数视为求和的初始值(如果没有给出,则使用
0
,这种情况下会出现错误)

因为您是对嵌套列表求和,所以实际得到的是
[1,3]+[2,4]
,结果是
求和([[1,3],[2,4]],[])
,它等于
[1,3,2,4]


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

给定列表列表
t

flat_list=[子列表中的项目对应于子列表中的项目]
这意味着:

flat_list = []
for sublist in t:
    for item in sublist:
        flat_list.append(item)
比目前发布的快捷方式快。(
t
是要展平的列表。)

下面是相应的函数:

flatten = lambda t: [item for sublist in t for item in sublist]
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
作为证据,您可以使用标准库中的
timeit
模块:

$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' '[item for sublist in t for item in sublist]'
10000 loops, best of 3: 143 usec per loop
$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(t, [])'
1000 loops, best of 3: 969 usec per loop
$ python -mtimeit -s't=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'reduce(lambda x,y: x+y,t)'
1000 loops, best of 3: 1.1 msec per loop
说明:当存在T个子列表时,基于
+
的快捷方式(包括
sum
中的隐含用法)必然是
O(T**2)
——随着中间结果列表不断变长,每一步都会分配一个新的中间结果列表对象,并且必须复制上一个中间结果中的所有项目(以及最后添加的一些新项目)。因此,为简单起见,在不实际失去一般性的情况下,假设每个k项都有T个子列表:第一个k项被来回复制T-1次,第二个k项被复制T-2次,依此类推;总拷贝数是从1到T的x的x之和的k倍,即
k*(T**2)/2

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

为什么使用extend

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

这应该行得通。

我收回我的声明。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]] * 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在适当的位置扩展了一个数组,但没有返回它。您仍然可以使用如下方式从lambda返回x:

reduce(lambda x,y: x.extend(y) or x, l)
注意:扩展比列表上的+更有效。

您可以使用:

或者,您可以使用不需要解压缩列表的:

也可以使用NumPy的:


2016年2月11日编辑:仅当子列表的维度相同时才有效。

似乎与
运算符混淆。添加
!当您同时添加两个列表时,正确的术语是
concat
,而不是add<代码>运算符。concat是您需要使用的

如果你想的是功能性的,那么就这么简单::

>>> 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)
你看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
来自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

如果您愿意为了更干净的外观而放弃少量的速度,那么您可以使用
numpy.concatenate().tolist()
numpy.concatenate().ravel().tolist()


您可以在文档中找到更多信息,上面Anil函数的一个坏特性是,它要求用户始终手动将第二个参数指定为空列表
[]
。这应该是默认设置。由于Python对象的工作方式,这些对象应该在函数内部设置,而不是在参数中设置

这里有一个工作函数:

flatten = lambda t: [item for sublist in t for item in sublist]
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]

如果您想将不知道嵌套深度的数据结构展平,可以使用1

它是一个生成器,因此您需要将结果强制转换为
列表
,或者显式地对其进行迭代


要仅展平一层,并且如果每个项目本身都是可折叠的,您也可以使用它本身只是一个薄薄的包装:


只需添加一些计时(基于Nico Schlömer答案,该答案不包括本答案中给出的函数):

这是一个对数图,用于容纳跨越的巨大值范围。对于定性推理:越低越好

结果表明,如果iterable只包含几个内部iterable,那么
sum
将是最快的,但是对于长iterable,只有
itertools.chain.from_iterable
iteration\u utilities.deepflatte
或嵌套理解具有合理的性能,
itertools.chain.from\u iterable
是最快的(Nico Schlömer已经注意到)



1免责声明:我是该库的作者

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


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

将其转换回列表。这里有一种通用方法,适用于数字字符串嵌套的列表和混合的容器。这可以使简单和复杂的内容变得平坦
>>> list2d = ((1, 2, 3),(4, 5, 6), (7,), (8, 9))
>>> %timeit reduce(operator.concat, list2d)
1000000 loops, best of 3: 492 ns per loop
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

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
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]
>>> 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]
>>> 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]
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()
import numpy as np
#turn list into an array and flatten()
np.array(l).flatten()
from typing import Iterable 
#from collections import Iterable                            # < py38


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
simple = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
list(flatten(simple))
# [1, 2, 3, 4, 5, 6, 7, 8, 9]

complicated = [[1, [2]], (3, 4, {5, 6}, 7), 8, "9"]              # numbers, strs, nested & mixed
list(flatten(complicated))
# [1, 2, 3, 4, 5, 6, 7, 8, '9']
> pip install more_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]
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]
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 install underscore.py
>>> 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]
def flatten(alist):
    if alist == []:
        return []
    elif type(alist) is not list:
        return [alist]
    else:
        return flatten(alist[0]) + flatten(alist[1:])
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]
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
>>> 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]
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']
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]
>>> 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))
>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))
>>> from matplotlib.cbook import flatten
>>> list(flatten(l))
>>> from unipath.path import flatten
>>> list(flatten(l))
>>> from setuptools.namespaces import flatten
>>> list(flatten(l))
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]]
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',
    )
def flatten(lst):
    for item in lst:
        if isinstance(item, list):
            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]

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]
f = []
list(map(f.extend, l))