簡體   English   中英

遞歸獲取嵌套列表的所有元素

[英]Get all elements of nested lists with recursion

〜來自這個Edabit挑戰

我需要獲取嵌套列表的所有元素,並使用遞歸將它們全部放在一個列表中。

我下面的代碼打印出每個元素,但是如何將它們全部保存到一個列表中並返回它們?

它必須保持在函數的范圍內。 我無法添加全局列表並附加所有列表。 它在技術上有效,但不適用於我試圖通過的挑戰。

我打印了這些值(代碼中的 var x ),因為這表明我已經接近了(我認為)。 我只需要一種方法將值返回給我的函數並將其附加到我最終將返回的列表中。

例子:
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']

編輯:如果您想專門返回列表,請使用

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_

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

在深度 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

他們的第二個解決方案使用“隊列”(但實際上將其視為“反向”堆棧,僅在左側擴展/彈出)。 我認為普通的堆棧(使用列表)更自然更簡單:

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 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直到我們得到非列表元素。

第二種解決方案

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 1st 解決方案的相同波長:

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

暫無
暫無

聲明:本站的技術帖子網頁,遵循CC BY-SA 4.0協議,如果您需要轉載,請注明本站網址或者原文地址。任何問題請咨詢:yoyou2525@163.com.

 
粵ICP備18138465號  © 2020-2024 STACKOOM.COM