在python中递归展平嵌套列表

2024-09-28 18:50:28 发布

您现在位置:Python中文网/ 问答频道 /正文

我在Python中使用生成器,并尝试使用简单递归方案来实现一个平坦函数。也就是说,一个函数接受一个可能包含子列表的列表作为输入,并输出一个只迭代输入的原子元素的iterable对象。在

因此,print(list(flatten([1,2,3,[4,5,6]])))应该返回包含[1,2,3,4,5,6]的内容。在

我的尝试如下:

def flatten(toflatten):
    try:
        for element in toflatten:
            flatten(element)
    except TypeError:
        yield toflatten

因此,它应该检查它的参数是否是iterable对象。如果是这种情况,也可以在该对象上递归。否则,将其作为原子元素生成。在

这不起作用,flatten([1,2,3,[4,5,6]])只返回一个空列表。在

为什么会这样?尤其是,为什么它甚至不在这个输入上执行递归函数调用呢?(我使用的是python3.5)


Tags: 对象函数元素内容列表def方案element
1条回答
网友
1楼 · 发布于 2024-09-28 18:50:28

所以,你想把名单弄平。你是在正确的轨道上,但你犯了几个错误。给你。在

  1. 将您的try-except移到循环内。在您的代码中,如果为一个元素引发TypeError,那么循环将停止运行。你不希望发生这种事。

  2. 在尝试中,你什么也没做。只进行函数调用。你也应该从那里归还一些东西。如果你有python3.3+,我推荐yield from

  3. 最后,在except中,您需要yield element,而不是{}。不要交出全部名单。

def flatten(toflatten):    
   for element in toflatten:
       try:
           yield from flatten(element)
       except TypeError:
           yield element

这给了我们

^{pr2}$

请求原谅比过去更容易。这是一种方法(实际上是我最喜欢的),但也有一个缺点:这会在字符串上崩溃。


还有另一种方法:LYBL(三思而后行)。它包括更加谨慎,使用if语句,这样就不会产生错误。在

def flatten(toflatten):    
   for element in toflatten:
       if isinstance(element, list):
           yield from flatten(element)
       else:
           yield element

它的工作原理和以前一样

^{pr2}$

然而,这是有利的,因为yield from生成器委托仅在子列表上调用。我有没有提到它也可以和字符串元素一起工作?在

>>> list(flatten([1,2,3,[4,5,'abc']]))
[1, 2, 3, 4, 5, 'abc']

请注意,在这两种情况下,如果您有递归定义的列表,则需要注意无限递归。例如,flatten将使用这种类型的输入崩溃。在

x = [1, 2, 3]
x.append(x)

flatten(x)

您将得到一个运行时错误:

RuntimeError: maximum recursion depth exceeded

相关问题 更多 >