是的,我知道这个主题之前已经被讨论过了:
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
这是最好的方法吗?我是不是忽略了什么?任何问题吗?
这是我的递归flatten的函数版本,它可以处理元组和列表,并允许您抛出任何位置参数的混合。返回一个生成器,它会逐参数依次生成整个序列:
flatten = lambda *n: (e for a in n
for e in (flatten(*a) if isinstance(a, (tuple, list)) else (a,)))
用法:
l1 = ['a', ['b', ('c', 'd')]]
l2 = [0, 1, (2, 3), [[4, 5, (6, 7, (8,), [9]), 10]], (11,)]
print list(flatten(l1, -2, -1, l2))
['a', 'b', 'c', 'd', -2, -1, 0, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 11]
我在这里没有看到类似的帖子,只是从一个关于同一主题的封闭问题中得到的,但为什么不做这样的事情呢(如果你知道你想拆分的列表类型):
>>> a = [1, 2, 3, 5, 10, [1, 25, 11, [1, 0]]]
>>> g = str(a).replace('[', '').replace(']', '')
>>> b = [int(x) for x in g.split(',') if x.strip()]
你需要知道元素的类型,但我认为这是可以推广的,就速度而言,我认为它会更快。
我更喜欢简单的答案。没有发电机。没有递归或递归限制。迭代:
def flatten(TheList):
listIsNested = True
while listIsNested: #outer loop
keepChecking = False
Temp = []
for element in TheList: #inner loop
if isinstance(element,list):
Temp.extend(element)
keepChecking = True
else:
Temp.append(element)
listIsNested = keepChecking #determine if outer loop exits
TheList = Temp[:]
return TheList
这适用于两个列表:一个内部for循环和一个外部while循环。
内部的for循环遍历列表。如果它发现一个列表元素,它(1)使用list.extend()将第一级嵌套的部分平铺,(2)将keepChecking切换为True。Keepchecking用于控制外部while循环。如果外部循环被设置为true,它将触发内部循环进行另一次传递。
这些传递一直发生,直到没有找到更多的嵌套列表为止。当最终发生传递而没有发现任何传递时,keepChecking永远不会被触发为true,这意味着listIsNested保持为false,外部while循环退出。
然后返回扁平的列表。
一起测试
flatten([1,2,3,4,[100,200,300,[1000,2000,3000]]])
[1, 2, 3, 4, 100, 200, 300, 1000, 2000, 3000]
这是一个简单的函数,它将任意深度的列表平展。不递归,避免堆栈溢出。
from copy import deepcopy
def flatten_list(nested_list):
"""Flatten an arbitrarily nested list, without recursion (to avoid
stack overflows). Returns a new list, the original list is unchanged.
>> list(flatten_list([1, 2, 3, [4], [], [[[[[[[[[5]]]]]]]]]]))
[1, 2, 3, 4, 5]
>> list(flatten_list([[1, 2], 3]))
[1, 2, 3]
"""
nested_list = deepcopy(nested_list)
while nested_list:
sublist = nested_list.pop(0)
if isinstance(sublist, list):
nested_list = sublist + nested_list
else:
yield sublist