Python 如何从列表列表中生成一个简单的列表?
在Python中,有没有一种快捷方式可以从列表列表中生成一个简单的列表 我可以在Python 如何从列表列表中生成一个简单的列表?,python,list,multidimensional-array,flatten,Python,List,Multidimensional Array,Flatten,在Python中,有没有一种快捷方式可以从列表列表中生成一个简单的列表 我可以在for循环中完成,但可能有一些很酷的“一行程序”?我用functools.reduce() 但我得到了这个错误: 回溯(最近一次呼叫最后一次): 文件“”,第1行,在 文件“”,第1行,在 AttributeError:“非类型”对象没有属性“扩展” 示例中的extend()方法修改x,而不是返回一个有用的值(期望) 执行reduce版本的更快方法是 >>> import operator >
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]
示例中的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]
请注意,仅适用于列表列表。对于列表列表列表,您需要另一种解决方案。作者的说明:这是低效的。但是很有趣,因为你很棒。它不适用于生产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
列表理解只生成一个列表,一次,并将每个项目复制(从其原始居住地复制到结果列表)一次。给定列表
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)
这应该可以正常工作。为什么要使用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
我收回我的声明。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)
注意:extend比list上的+更有效。函数不起作用的原因是extend在适当的位置扩展了一个数组,而没有返回它。您仍然可以使用如下方式从lambda返回x:
reduce(lambda x,y: x.extend(y) or x, l)
注意:扩展比列表上的+更有效。您可以使用:
或者您可以使用不需要unpac的
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))