是的,我知道以前已经讨论过这个主题( 在这里 , 这里 , 这里 , 这里 ),但是据我所知,除一个解决方案外,所有解决方案在这样的列表上均失败:
L = [[[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(L)
这是最好的模型吗? 我有事吗 任何问题?
#1楼
使用递归和鸭子类型生成器(针对Python 3更新):
def flatten(L):
for item in L:
try:
yield from flatten(item)
except TypeError:
yield item
list(flatten([[[1, 2, 3], [4, 5]], 6]))
>>>[1, 2, 3, 4, 5, 6]
#2楼
尝试创建一个可以平化Python中不规则列表的函数很有趣,但是当然这就是Python的目的(使编程变得有趣)。 以下生成器在某些警告方面工作得很好:
def flatten(iterable):
try:
for item in iterable:
yield from flatten(item)
except TypeError:
yield iterable
它将扁平化您可能希望单独保留的数据类型(例如bytearray
, bytes
和str
对象)。 此外,代码还依赖于以下事实:从不可迭代的对象请求迭代器会引发TypeError
。
>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> def flatten(iterable):
try:
for item in iterable:
yield from flatten(item)
except TypeError:
yield iterable
>>> list(flatten(L))
[1, 2, 3, 4, 5, 6]
>>>
编辑:
我不同意以前的实现。 问题在于您不应该将无法迭代的东西弄平。 这令人困惑,并给人以错误的印象。
>>> list(flatten(123))
[123]
>>>
以下生成器与第一个生成器几乎相同,但是不存在试图展平不可迭代对象的问题。 当给它一个不适当的参数时,它会像人们期望的那样失败。
def flatten(iterable):
for item in iterable:
try:
yield from flatten(item)
except TypeError:
yield item
使用提供的列表对生成器进行测试可以正常工作。 但是,新代码在给它一个不可迭代的对象时将引发TypeError
。 下面显示了新行为的示例。
>>> L = [[[1, 2, 3], [4, 5]], 6]
>>> list(flatten(L))
[1, 2, 3, 4, 5, 6]
>>> list(flatten(123))
Traceback (most recent call last):
File "<pyshell#32>", line 1, in <module>
list(flatten(123))
File "<pyshell#27>", line 2, in flatten
for item in iterable:
TypeError: 'int' object is not iterable
>>>
#3楼
这里的compiler.ast.flatten
在2.7.5的实现:
def flatten(seq):
l = []
for elt in seq:
t = type(elt)
if t is tuple or t is list:
for elt2 in flatten(elt):
l.append(elt2)
else:
l.append(elt)
return l
有更好,更快的方法(如果您已经到达这里,您已经看到了它们)
另请注意:
自2.6版起弃用:编译器软件包已在Python 3中删除。
#4楼
这是一个简单的函数,可以平铺任意深度的列表。 没有递归,以避免堆栈溢出。
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
#5楼
我的解决方案:
import collections
def flatten(x):
if isinstance(x, collections.Iterable):
return [a for i in x for a in flatten(i)]
else:
return [x]
更加简洁,但几乎相同。
来源:oschina
链接:https://my.oschina.net/u/3797416/blog/3163097