在Python中压扁任意嵌套列表的最快方法是什么?

可能重复:
在Python中展开浅表
在Python中展开列表(不规则)列表

编辑:这需要与任何数量的嵌套级别,而不仅仅是一个。

我已经find解决scheme之前,但我想知道什么最快的解决办法是扁平列表包含其他任意长度的列表。

例如:

[1, 2, [3, 4, [5],[]], [6]] 

会成为:

 [1,2,3,4,5,6] 

可以有无限多的层次。 一些列表对象可以是string,不能将它们拼合成输出列表中的顺序字符。

这是一个string友好的recursion方法:

 nests = [1, 2, [3, 4, [5],['hi']], [6, [[[7, 'hello']]]]] def flatten(container): for i in container: if isinstance(i, (list,tuple)): for j in flatten(i): yield j else: yield i print list(flatten(nests)) 

收益:

 [1, 2, 3, 4, 5, 'hi', 6, 7, 'hello'] 

请注意,这不能保证速度或开销的使用,但是说明了一个recursion的解决scheme,希望这会有帮助。

它不一定是recursion的。 实际上,由于函数调用的开销,迭代解决scheme通常更快。 下面是我之前写的一个迭代版本:

 def flatten(items, seqtypes=(list, tuple)): for i, x in enumerate(items): while i < len(items) and isinstance(items[i], seqtypes): items[i:i+1] = items[i] return items 

还没有testing过这个具体实现的性能,但是由于所有的slice分配都可能不是很好,最终可能会移动大量的内存。 不过,不要认为它必须是recursion的,或者这样写就更简单了。

这个实现的好处是可以将列表展平,而不是返回一个副本,因为recursion的解决scheme总是这样做的。 当内存紧张时这可能是有用的。 如果你想要一个扁平化的副本,只需传入你想扁平的列表的浅表副本:

 flatten(mylist) # flattens existing list newlist = flatten(mylist[:]) # makes a flattened copy 

而且,这个algorithm不受Pythonrecursion限制的限制,因为它不是recursion的。 但是,我确信这个问题几乎不会发挥作用。

这个函数应该能够在不使用任何recursion的情况下快速地压扁嵌套的可迭代容器:

 import collections def flatten(iterable): iterator = iter(iterable) array, stack = collections.deque(), collections.deque() while True: try: value = next(iterator) except StopIteration: if not stack: return tuple(array) iterator = stack.pop() else: if not isinstance(value, str) \ and isinstance(value, collections.Iterable): stack.append(iterator) iterator = iter(value) else: array.append(value) 

大约五年后,我对这个问题的看法已经改变了,这可能会更好用:

 def main(): data = [1, 2, [3, 4, [5], []], [6]] print(list(flatten(data))) def flatten(iterable): iterator, sentinel, stack = iter(iterable), object(), [] while True: value = next(iterator, sentinel) if value is sentinel: if not stack: break iterator = stack.pop() elif isinstance(value, str): yield value else: try: new_iterator = iter(value) except TypeError: yield value else: stack.append(iterator) iterator = new_iterator if __name__ == '__main__': main()