是的,我知道这个主题之前已经被讨论过了:
Python成语链(扁平化)有限迭代对象的无限迭代?
在Python中扁平化一个浅列表
理解平展一个序列的序列吗?
我如何从列表的列表中创建一个平面列表?
但据我所知,所有的解决方案,除了一个,在像[[[1,2,3],[4,5]],6]这样的列表上失败,其中期望的输出是[1,2,3,4,5,6](或者更好,一个迭代器)。
我看到的唯一解决方案,适用于任意嵌套是在这个问题:
def flatten(x):
result = []
for el in x:
if hasattr(el, "__iter__") and not isinstance(el, basestring):
result.extend(flatten(el))
else:
result.append(el)
return result
这是最好的方法吗?我是不是忽略了什么?任何问题吗?
没有装饰。只有发冷。
recursive_list_of_lists = [1,2,3,[1,2,[[3,4,[5]],7,0,1,10],100,[101,[101,[[101]],2]],0]]
k = []
def flatten(subl):
for i in subl:
if type(i) != type([1]):
k.append(i)
else:
flatten(i)
flatten(recursive_list_of_lists)
print(k)
[1, 2, 3, 1, 2, 3, 4, 5, 7, 0, 1, 10, 100, 101, 101, 101, 2, 0]
我知道已经有很多很棒的答案,但我想添加一个答案,使用函数式编程方法来解决这个问题。在这个答案中,我使用了双重递归:
def flatten_list(seq):
if not seq:
return []
elif isinstance(seq[0],list):
return (flatten_list(seq[0])+flatten_list(seq[1:]))
else:
return [seq[0]]+flatten_list(seq[1:])
print(flatten_list([1,2,[3,[4],5],[6,7]]))
输出:
[1, 2, 3, 4, 5, 6, 7]
大多数答案都使用循环遍历条目。这里我有一个使用EAFP方法的变体:尝试在输入上获得一个迭代器,如果成功,首先在第一个元素上运行函数,然后在这个迭代器的其余部分上运行。如果你不能得到迭代器,或者它是一个字符串或字节对象:产生元素。
感谢A. Kareem的建议,他发现我的代码非常慢,因为对字符串和字节对象的递归花费了太长时间,这里是我的代码的改进版本。
def flatten(x, it = None):
try:
if type(x) in (str, bytes):
yield x
else:
if not it:
it = iter(x)
yield from flatten(next(it))
if type(x) not in (str, bytes):
yield from flatten(x, it)
except StopIteration:
pass
except Exception:
yield x
oldlist = [1,[[[["test",3]]]],((4,5,6)),[ bytes("test", encoding="utf-8"),7,[8,9]]]
newlist = [ x for x in flatten(oldlist) ]
print(newlist)
# [1, 'test', 3, 4, 5, 6, b'test', 7, 8, 9]
我使用递归解决嵌套列表与任何深度
def combine_nlist(nlist,init=0,combiner=lambda x,y: x+y):
'''
apply function: combiner to a nested list element by element(treated as flatten list)
'''
current_value=init
for each_item in nlist:
if isinstance(each_item,list):
current_value =combine_nlist(each_item,current_value,combiner)
else:
current_value = combiner(current_value,each_item)
return current_value
所以在我定义函数combine_nlist之后,很容易使用这个函数来做flatting。或者你可以把它组合成一个函数。我喜欢我的解决方案,因为它可以应用于任何嵌套列表。
def flatten_nlist(nlist):
return combine_nlist(nlist,[],lambda x,y:x+[y])
结果
In [379]: flatten_nlist([1,2,3,[4,5],[6],[[[7],8],9],10])
Out[379]: [1, 2, 3, 4, 5, 6, 7, 8, 9, 10]