Emm*_*mma 2950 python list flatten multidimensional-array
我想知道是否有一条快捷方式可以在Python列表中列出一个简单的列表.
我可以在for循环中做到这一点,但也许有一些很酷的"单行"?我用reduce尝试了,但是我收到了一个错误.
码
l = [[1, 2, 3], [4, 5, 6], [7], [8, 9]]
reduce(lambda x, y: x.extend(y), l)
Run Code Online (Sandbox Code Playgroud)
错误信息
Traceback (most recent call last):
File "<stdin>", line 1, in <module>
File "<stdin>", line 1, in <lambda>
AttributeError: 'NoneType' object has no attribute 'extend'
Run Code Online (Sandbox Code Playgroud)
Ale*_*lli 4260
给出列表清单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)
Run Code Online (Sandbox Code Playgroud)
比目前发布的快捷方式快.(l
是要压扁的列表.)
这是相应的功能:
flatten = lambda l: [item for sublist in l for item in sublist]
Run Code Online (Sandbox Code Playgroud)
作为证据,您可以使用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
Run Code Online (Sandbox Code Playgroud)
说明:当存在L个子列表时,基于+
(包括隐含用途sum
)的快捷方式是必要的O(L**2)
- 当中间结果列表持续变长时,在每个步骤分配新的中间结果列表对象,以及所有项目必须复制之前的中间结果(以及最后添加的一些新结果).因此,为了简单而没有实际失去一般性,请说每个项目都有L个子列表:第一个I项目来回复制L-1次,第二个I项目L-2次,依此类推; 总复制数是I乘以x的总和,从1到L排除,即I * (L**2)/2
.
列表理解只生成一个列表一次,并将每个项目(从其原始居住地点到结果列表)复制一次.
Sha*_*hin 1388
你可以使用itertools.chain()
:
>>> import itertools
>>> list2d = [[1,2,3], [4,5,6], [7], [8,9]]
>>> merged = list(itertools.chain(*list2d))
Run Code Online (Sandbox Code Playgroud)
或者,在Python> = 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))
Run Code Online (Sandbox Code Playgroud)
这种方法可以说更具可读性,*
而且看起来也更快:
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;import itertools' 'list(itertools.chain.from_iterable(l))'
20000 loops, best of 5: 10.8 usec per loop
$ python3 -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 5: 21.7 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99' 'sum(l, [])'
1000 loops, best of 5: 258 usec per loop
$ python3 -mtimeit -s'l=[[1,2,3],[4,5,6], [7], [8,9]]*99;from functools import reduce' 'reduce(lambda x,y: x+y,l)'
1000 loops, best of 5: 292 usec per loop
$ python3 --version
Python 3.7.5rc1
Run Code Online (Sandbox Code Playgroud)
Tri*_*ych 819
作者请注意:这是低效的.但有趣的是,因为幺半群很棒.它不适合生产Python代码.
>>> sum(l, [])
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
这只是对第一个参数中传递的iterable元素进行求和,将第二个参数视为总和的初始值(如果没有给出,0
则使用它,这种情况会给你一个错误).
因为你是对嵌套列表进行求和,所以实际得到[1,3]+[2,4]
的结果是sum([[1,3],[2,4]],[])
,等于[1,3,2,4]
.
请注意,仅适用于列表列表.对于列表列表,您需要另一种解决方案.
Nic*_*mer 348
我用perfplot(我的一个宠物项目,基本上是一个包装物timeit
)测试了大多数建议的解决方案,并找到了
functools.reduce(operator.iconcat, a, [])
Run Code Online (Sandbox Code Playgroud)
成为最快的解决方案.(operator.iadd
同样快.)
重现情节的代码:
import functools
import itertools
import numpy
import operator
import perfplot
def forfor(a):
return [item for sublist in a for item in sublist]
def sum_brackets(a):
return sum(a, [])
def functools_reduce(a):
return functools.reduce(operator.concat, a)
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 numpy_concatenate(a):
return list(numpy.concatenate(a))
perfplot.show(
setup=lambda n: [list(range(10))] * n,
kernels=[
forfor, sum_brackets, functools_reduce, functools_reduce_iconcat,
itertools_chain, numpy_flat, numpy_concatenate
],
n_range=[2**k for k in range(16)],
logx=True,
logy=True,
xlabel='num lists'
)
Run Code Online (Sandbox Code Playgroud)
Gre*_*ill 158
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]
Run Code Online (Sandbox Code Playgroud)
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]
Run Code Online (Sandbox Code Playgroud)
pyl*_*ang 96
以下是适用于数字,字符串,嵌套列表和混合容器的一般方法.
码
#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
Run Code Online (Sandbox Code Playgroud)
注意:在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']
Run Code Online (Sandbox Code Playgroud)
参考
MSe*_*ert 43
如果你想展平一个你不知道嵌套深度的数据结构,你可以使用1iteration_utilities.deepflatten
>>> 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]
Run Code Online (Sandbox Code Playgroud)
它是一个生成器,因此您需要将结果转换为a list
或显式迭代它.
要展平只有一个级别,如果每个项目本身都是可迭代的,你也可以使用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]
Run Code Online (Sandbox Code Playgroud)
只是添加一些时间(基于NicoSchlömer的答案,不包括此答案中提供的功能):
这是一个对数日志图,可以适应各种各样的值.对于定性推理:越低越好.
研究结果表明,如果迭代只包含几个内部iterables然后sum
将最快,但长期iterables只itertools.chain.from_iterable
,iteration_utilities.deepflatten
或嵌套的理解与合理的性能itertools.chain.from_iterable
是最快的(如已被尼科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()
Run Code Online (Sandbox Code Playgroud)
1免责声明:我是该图书馆的作者
Max*_*ysh 39
>>> from django.contrib.admin.utils import flatten
>>> l = [[1,2,3], [4,5], [6]]
>>> flatten(l)
>>> [1, 2, 3, 4, 5, 6]
Run Code Online (Sandbox Code Playgroud)
... 熊猫:
>>> from pandas.core.common import flatten
>>> list(flatten(l))
Run Code Online (Sandbox Code Playgroud)
... Itertools:
>>> import itertools
>>> flatten = itertools.chain.from_iterable
>>> list(flatten(l))
Run Code Online (Sandbox Code Playgroud)
... Matplotlib
>>> from matplotlib.cbook import flatten
>>> list(flatten(l))
Run Code Online (Sandbox Code Playgroud)
... Unipath:
>>> from unipath.path import flatten
>>> list(flatten(l))
Run Code Online (Sandbox Code Playgroud)
... Setuptools:
>>> from setuptools.namespaces import flatten
>>> list(flatten(l))
Run Code Online (Sandbox Code Playgroud)
Nad*_*mli 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
Run Code Online (Sandbox Code Playgroud)
总和版本仍然运行超过一分钟,它还没有完成处理!
对于中等列表:
>>> 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
Run Code Online (Sandbox Code Playgroud)
使用小列表和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
Run Code Online (Sandbox Code Playgroud)
dtl*_*m26 36
根据你的列表[[1, 2, 3], [4, 5, 6], [7], [8, 9]]
是1级列表,我们可以简单地使用sum(list,[])
而不使用任何库
sum([[1, 2, 3], [4, 5, 6], [7], [8, 9]],[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
当内部存在元组或数字时,扩展此方法的优点。map
简单地为列表中的每个元素添加一个映射函数
#For only tuple
sum(list(map(list,[[1, 2, 3], (4, 5, 6), (7,), [8, 9]])),[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
#In general
def convert(x):
if type(x) is int or type(x) is float:
return [x]
else:
return list(x)
sum(list(map(convert,[[1, 2, 3], (4, 5, 6), 7, [8, 9]])),[])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
在这里,清楚地解释了这种方法在内存方面的缺点。简而言之,它递归地创建列表对象,这是应该避免的:(
Mei*_*ham 34
似乎有一种混乱operator.add
!当您将两个列表一起添加时,正确的术语是concat
,而不是添加.operator.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)
Run Code Online (Sandbox Code Playgroud)
你看到reduce尊重序列类型,所以当你提供一个元组时,你会得到一个元组.让我们尝试一下清单::
>>> list2d = [[1, 2, 3],[4, 5, 6], [7], [8, 9]]
>>> reduce(operator.concat, list2d)
[1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
啊哈,你得到一份清单.
性能怎么样::
>>> 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
Run Code Online (Sandbox Code Playgroud)
from_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
Run Code Online (Sandbox Code Playgroud)
And*_*mbu 31
为什么使用extend?
reduce(lambda x, y: x+y, l)
Run Code Online (Sandbox Code Playgroud)
这应该工作正常.
pyl*_*ang 22
考虑安装more_itertools
包.
> pip install more_itertools
Run Code Online (Sandbox Code Playgroud)
它附带了一个实现flatten
(源代码,来自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]
Run Code Online (Sandbox Code Playgroud)
从版本2.4开始,您可以使用more_itertools.collapse
(源代码,由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]
Run Code Online (Sandbox Code Playgroud)
Igo*_*kon 20
您的函数不起作用的原因:extend将数组扩展到原位并且不返回它.您仍然可以使用一些技巧从lambda返回x:
reduce(lambda x,y: x.extend(y) or x, l)
Run Code Online (Sandbox Code Playgroud)
注意:extend比列表上的+更有效.
Ani*_*nil 14
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]
Run Code Online (Sandbox Code Playgroud)
Del*_*eet 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
Run Code Online (Sandbox Code Playgroud)
测试:
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]
Run Code Online (Sandbox Code Playgroud)
use*_*332 12
在处理基于文本的可变长度列表时,接受的答案对我不起作用.这是一种替代方法,对我有用.
l = ['aaa', 'bb', 'cccccc', ['xx', 'yyyyyyy']]
Run Code Online (Sandbox Code Playgroud)
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']
Run Code Online (Sandbox Code Playgroud)
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']
Run Code Online (Sandbox Code Playgroud)
小智 12
递归版本
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]
Run Code Online (Sandbox Code Playgroud)
mmj*_*mmj 12
有几个答案具有与下面相同的递归附加方案,但没有一个使用try
,这使得解决方案更加健壮和Pythonic。
def flatten(itr):
for x in itr:
try:
yield from flatten(x)
except TypeError:
yield x
Run Code Online (Sandbox Code Playgroud)
用法:这是一个生成器,您通常希望将其包含在可迭代的构建器中,例如list()
ortuple()
或在循环中使用它for
。
该解决方案的优点是:
注意:由于所有可迭代对象都被展平,因此字符串被分解为单个字符的序列。如果您不喜欢/想要这种行为,您可以使用以下版本,该版本可以过滤掉字符串和字节等扁平可迭代对象:
def flatten(itr):
if type(itr) in (str,bytes):
yield itr
else:
for x in itr:
try:
yield from flatten(x)
except TypeError:
yield x
Run Code Online (Sandbox Code Playgroud)
EL_*_*DON 11
matplotlib.cbook.flatten()
即使它们比示例更深入嵌套,它也适用于嵌套列表.
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))
Run Code Online (Sandbox Code Playgroud)
结果:
[1, 2, 3, 4, 5, 6, 7, 8, 9]
[1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11, 12, 13]
Run Code Online (Sandbox Code Playgroud)
这比下划线快18倍._.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
Run Code Online (Sandbox Code Playgroud)
以下对我来说似乎最简单:
>>> 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]
Run Code Online (Sandbox Code Playgroud)
也可以使用NumPy的公寓:
import numpy as np
list(np.array(l).flat)
Run Code Online (Sandbox Code Playgroud)
编辑11/02/2016:仅当子列表具有相同的尺寸时才有效.
您可以使用list
extend
方法,它显示是最快的:
flat_list = []
for sublist in l:
flat_list.extend(sublist)
Run Code Online (Sandbox Code Playgroud)
表现:
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',
)
Run Code Online (Sandbox Code Playgroud)
如果您愿意放弃少量速度以获得更清洁的外观,那么您可以使用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
Run Code Online (Sandbox Code Playgroud)
您可以在文档numpy.concatenate和numpy.ravel 中找到更多信息。
underscore.py
包装风扇的简单代码
from underscore import _
_.flatten([[1, 2, 3], [4, 5, 6], [7], [8, 9]])
# [1, 2, 3, 4, 5, 6, 7, 8, 9]
Run Code Online (Sandbox Code Playgroud)
它解决了所有扁平化问题(无列表项或复杂的嵌套)
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]
Run Code Online (Sandbox Code Playgroud)
您可以underscore.py
使用pip 安装
pip install underscore.py
Run Code Online (Sandbox Code Playgroud)
def flatten(alist):
if alist == []:
return []
elif type(alist) is not list:
return [alist]
else:
return flatten(alist[0]) + flatten(alist[1:])
Run Code Online (Sandbox Code Playgroud)
注意:以下适用于 Python 3.3+,因为它使用yield_from
. six
也是第三方包,虽然它很稳定。或者,您可以使用sys.version
.
在 的情况下obj = [[1, 2,], [3, 4], [5, 6]]
,这里的所有解决方案都很好,包括列表理解和itertools.chain.from_iterable
.
但是,请考虑这种稍微复杂的情况:
>>> obj = [[1, 2, 3], [4, 5], 6, 'abc', [7], [8, [9, 10]]]
Run Code Online (Sandbox Code Playgroud)
这里有几个问题:
6
,只是一个标量;它不是可迭代的,所以上面的路线在这里会失败。'abc'
,是技术上可迭代(所有str
s为)。但是,在两行之间稍微阅读一下,您不想将其视为这样 - 您想将其视为单个元素。[8, [9, 10]]
本身是一个嵌套的可迭代对象。基本列表理解,chain.from_iterable
只提取“1级”。您可以通过以下方式解决此问题:
>>> 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]
Run Code Online (Sandbox Code Playgroud)
在这里,您检查子元素 (1) 是否可使用Iterable
、来自 的 ABC 进行迭代itertools
,但还希望确保 (2) 元素不是“类似字符串的”。
flat_list = []
for i in list_of_list:
flat_list+=i
Run Code Online (Sandbox Code Playgroud)
该代码也可以很好地工作,因为它会一直扩展列表。虽然非常相似,但是只有一个for循环。因此,它比添加2 for循环具有更少的复杂性。
归档时间: |
|
查看次数: |
1840012 次 |
最近记录: |