我有一个小问题,我缺乏一些Python经验。 假设一个清单:
list=[[40, 20, 45, 40], [[20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]]
我想做一些我称之为“部分扁平化”的事情。因为预期的输出是:
[[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]
在list
的{{1}}之前注意,而预期输出的长度为2
。问题是我事先并不知道3
中哪个元素嵌套了一层。
This answer和许多其他人没有多大帮助,因为扁平化走得很远。在问题之后输出是:
list
(注意列表中前4个元素的缺失括号。
答案 0 :(得分:1)
您可以创建一个递归函数,测试all
内部元素是否为列表。如果是这样,则递归地应用算法,否则产生列表本身。
def inner_lists(lst):
if all(isinstance(x, list) for x in lst):
for inner in lst:
for x in inner_lists(inner):
yield x
else:
yield lst
>>> lst = [[40, 20, 45, 40], [[20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]]
>>> list(inner_lists(lst))
[[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]
或使用yield from
(Python 3.3及更高版本):
def inner_lists(lst):
if all(isinstance(x, list) for x in lst):
yield from (x for inner in lst for x in inner_lists(inner))
else:
yield lst
或没有发电机:
def inner_lists(lst):
if all(isinstance(x, list) for x in lst):
return [x for inner in lst for x in inner_lists(inner)]
else:
return [lst]
答案 1 :(得分:1)
如果您的列表只能包含数字或子列表(不是两者),您可以使用以下生成器功能:
In [25]: def partial_flattening(lst):
for sub in lst:
if isinstance(sub[0], list):
yield from sub # in python 2.x use for i in sub: yeild i
else:
yield sub
....:
In [26]: list(partial_flattening(lst))
Out[36]: [[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]
如果可能有两种类型的组合,那么根据您想要对数字进行的操作,您可以自定义该功能。
或者作为一种更简洁的方法,您可以在列表理解中使用yield
:
In [29]: list([(yield from i) if isinstance(i[0], list) else (yield i) for i in lst])
Out[29]: [[40, 20, 45, 40], [20, 10, 10, 30, 45, 20], [30, 20, 20, 30]]