def flattenList(toFlatten):
final=[]
for el in toFlatten:
if isinstance(el, list):
final.extend(flattenList(el))
else:
final.append(el)
return final
当我不知道列表的嵌套程度时,这是我能想到的唯一方法。
答案 0 :(得分:7)
你应该避免在Python中进行类型检查。在这种情况下,这意味着避免任意嵌套的结构,您可以按类型区分。您可以构建自己的节点类型,您可以通过方法其他遍历而不是类型检查,例如查看特定属性。
要展平一个级别或n个级别,请查看itertools.chain.from_iterable
。
我不知道你的意思是“功能性”。这段代码非常实用:它使用递归(不是它的功劳!)并且它不会改变它的参数。 (严格来说,它确实使用可变状态来构建列表,但这就是你在Python中的表现。
我想一个更多的功能属性是延迟评估。你可以这样实现这个
def flatten(toFlatten):
for item in toFlatten:
if isinstance(item, list): # Ewww, typchecking
for subitem in flatten(item): # they are considering adding
yield subitem # "yield from" to the language
# to give this pattern syntax
else:
yield item
Python中的递归非常有限(至少在所有主要实现中都是如此),并且通常应该避免任意深度。很有可能重写这个(和所有递归代码)来使用迭代,这将使它更具可扩展性(并且功能更少,这在Python中是一件好事,它不是特别适合FP。)
< / LI> 醇>答案 1 :(得分:3)
这个答案解释了为什么你不想在Python中使用reduce
。
考虑代码段
reduce(operator.add, [[1], [2], [3], [4], [5]])
这有什么作用?
[1] + [2] => [1, 2]
[1, 2] + [3] => This makes a new list, having to go over 1, then 2, then 3. [1, 2, 3]
[1, 2, 3] + [4] => This has to copy the 1, 2, and 3 and then put 4 in the new list
[1, 2, 3, 4] + [5] => The length of stuff I have to copy gets bigger each time!
这种二次行为是完全可以避免的:原始解决方案(以及任何数量的其他解决方案)不会形成这些中间复制步骤。
答案 2 :(得分:2)
这是另一种选择(虽然可能有一些比类型检查更清晰的东西,比如测试某些东西是否可迭代,因此不是“原子”):
def flatten(lst):
if not isinstance(lst,list):
return [lst]
else:
return reduce(lambda x,y:x+y,[flatten(x) for x in lst],[])
它基于类似计划的东西。
答案 3 :(得分:2)
在itertools的文档下,有一个flatten()
函数