使用递归获取嵌套列表的所有元素

Get all elements of nested lists with recursion

~ 来自 This Edabit Challenge ~

我需要获取嵌套列表的所有元素并使用递归将它们全部放在一个列表中。

我下面的代码打印出每个元素,但我如何将它们全部保存到一个列表和 return 他们?

它必须保持在功能范围内。我无法添加全局列表并附加所有列表。它在技术上可行,但不适用于我试图通过的挑战。

我打印了值(在代码中是 var x),因为这表明我正在接近(我认为)。我只需要一种方法 return 将值返回到我的函数并将其附加到我最终将 return.

的列表中

示例:
flatten([[[[[["direction"], [372], ["one"], [[[[[["Era"]]]], "Sruth", 3337]]], "First"]]]]) ➞ ["direction", 372, "one", "Era", "Sruth", 3337, "First"]

flatten([[4666], [5394], [466], [[["Saskia", [[[[["DXTD"]], "Lexi"]]]]]]]) ➞ [4666, 5394, 466, "Saskia", "DXTD", "Lexi"]

代码:


    def flatten(arr):   
        
        res = [] 
        if isinstance(arr, list):
            for i in arr:
                res.append(flatten(i))
        else:
            return arr
        if isinstance(res, list):
            for i in res:
                x = flatten(i)
                if x:
                    print(x)
            
    
    
    x = flatten([[[[[["direction"], [372], ["one"], [[[[[["Era"]]]], "Sruth", 3337]]], "First"]]]])
    print(main)

输出:

    direction
    372
    one
    Era
    Sruth
    3337
    First
    []

上面的输出显示我的代码遍历了每个非列表值。

传递一个列表以展平,并在每一步附加到它:

def flatten(arr, list_):
    if isinstance(arr, list):
        for i in arr:
            flatten(i, list_)
    else:
        list_.append(arr)


test = [['a'], 'b']
output = []
flatten(test, output)
output

['a', 'b']

编辑:如果你想专门return列表,使用

def flatten(arr, list_=None):
    if list_ is None:
        list_ = []
    if isinstance(arr, list):
        for i in arr:
            flatten(i, list_)
    else:
        list_.append(arr)
    return list_

我想提供两种解决方案:第一种使用递归,第二种使用队列。

第一个解决方案

def flatten_helper(nested):
    for e in nested:
        if isinstance(e, list):
            yield from flatten_helper(e)
        else:
            yield e
            
def flatten(nested):
    return list(flatten_helper(nested))

flatten_helper函数是一个生成器,生成一个不是列表的元素列表。如果一个元素是一个列表,我们再次调用 flatten_helper 直到我们得到 non-list 个元素。

第二种解决方案

import collections

def flatten(nested):
    queue = collections.deque(nested)
    out = []
    while queue:
        e = queue.popleft()
        if isinstance(e, list):
            queue.extendleft(reversed(e))
        else:
            out.append(e)
    return out

在此解决方案中,我们遍历嵌套列表。如果元素是一个列表,我们将每个子元素放入一个队列中以供以后处理。如果元素不是列表,我们将其附加到 out.

Hai Vu 解决方案的变化...

他们的第一个解决方案使用嵌套生成器,这意味着每个值都通过该生成器堆栈产生。如果结构嵌套很深,这会使解决方案总体上采用 二次方 而不是线性时间。另一种方法是在主函数中创建一个本地列表,并让辅助函数填充它。我更喜欢为此使用嵌套函数,这样我就不必四处传递列表,也不必将辅助函数暴露给外部。

def flatten(nested):
    flat = []
    def helper(nested):
        for e in nested:
            if isinstance(e, list):
                helper(e)
            else:
                flat.append(e)
    helper(nested)
    return flat

Benchmark 在深度 800 处有 800 个整数:

26.03 ms  Hai_Vu
 0.25 ms  Kelly
25.62 ms  Hai_Vu
 0.24 ms  Kelly
26.07 ms  Hai_Vu
 0.24 ms  Kelly

他们的第二个解决方案使用了一个“队列”(但实际上把它当作一个“反向”堆栈,extending/popping 只在左边)。我觉得普通的栈(使用列表)更自然也更简单:

def flatten(nested):
    stack = [nested]
    out = []
    while stack:
        e = stack.pop()
        if isinstance(e, list):
            stack += reversed(e)
        else:
            out.append(e)
    return out

另一种可能性......更多关于海武第一个解决方案的相同波长:

def flatter(lst):
    output = []
    for i in lst:
        if isinstance(i, list):
            output.extend(flatter(i))
        else:
            output.append(i)
    return output