簡體   English   中英

展平包含元組,字母和整數列表的列表

[英]Flattening a list that contains lists of tuples, letters and integers

我需要遞歸整理列表:

在列表看起來像之前:

L=[1,[2,[‘a’,(3,’b’)]],(5,6),([11,22])] 

后:

Lflat=[1,2,’a’,(3,’b’),(5,6),([11,22])]

我的代碼遇到問題(lst1為空的lst1)

def list_flatten(lst,lst1):
    for item in lst:
        if type(item) == tuple:
            print(item)
            lst1.append(item)
        elif type(item) == list:
            list_flatten(item,lst1)
        else:
            lst1.append(item)
    return lst1

這將返回以下內容:

輸出: [1, 2, 'a', (3, 'b'), (5, 6), 11, 22]

這使我發現([])被認為是列表,而不是元組。

現在我的問題如下:

  1. 假設我要在主程序中定義lst1 = []。 我如何做到這一點,以便遞歸不會在每次迭代中清空列表?
  2. 為什么([])被視為列表?

您的list_flatten函數會lst1參數,因此您實際上不需要返回任何內容。 您可以這樣稱呼它:

L = [1,[2,['a',(3,'b')]],(5,6),([11,22])] 

def list_flatten(lst, lst1):
    for item in lst:
        if isinstance(item, list):
            list_flatten(item, lst1)
        else:
            lst1.append(item)

Lflat = []
list_flatten(L, Lflat)
print(Lflat)

產量

[1, 2, 'a', (3, 'b'), (5, 6), 11, 22]

建議使用isinstance而不是type因為這會使代碼更具通用性:它也可用於源自list對象。

我們可以重新編寫該函數,以便您無需傳遞lst1

def list_flatten(lst, lst1=None):
    if lst1 is None:
        lst1 = []
    for item in lst:
        if isinstance(item, list):
            list_flatten(item, lst1)
        else:
            lst1.append(item)
    return lst1

Lflat = list_flatten(L)
print(Lflat)

我們給lst1一個默認值None ,在遞歸的頂層,我們將名字lst1重新綁定到一個空列表中以收集結果。

我們不能將lst1的默認值lst1 [] 這是因為默認args是在編譯函數時創建的,而不是在調用函數時創建的,並且如果我們為lst1默認值[] ,則每次調用都會使用相同的列表。 看起來像第一次使用list_flatten ,我們可以list_flatten它,但是在隨后的調用中卻無法達到預期的效果。 這是一個簡短的演示。

L = [1,[2,['a',(3,'b')]],(5,6),([11,22])] 

def list_flatten(lst, lst1=[]):
    for item in lst:
        if isinstance(item, list):
            list_flatten(item, lst1)
        else:
            lst1.append(item)
    return lst1

Lflat = list_flatten(L)
print(Lflat)
Lflat = list_flatten(L)
print(Lflat)

產量

[1, 2, 'a', (3, 'b'), (5, 6), 11, 22]
[1, 2, 'a', (3, 'b'), (5, 6), 11, 22, 1, 2, 'a', (3, 'b'), (5, 6), 11, 22]

如您所見, lst1保留了第一個調用的內容。 有關此重要主題的更多信息,請參見“最小驚訝”和可變默認參數 有時候,這種行為是可取的,但是在這種情況下,明智的做法是在代碼中添加注釋,而您有意使用可變的默認參數。


另一種方法是使list_flatten成為生成器,並將其輸出收集到列表中:

def list_flatten(lst):
    for item in lst:
        if isinstance(item, list):
            yield from list_flatten(item)
        else:
            yield item

Lflat = list(list_flatten(L))
print(Lflat)

在最新版本的Python中,您可以使用[*list_flatten(L)]替換list(list_flatten(L))

Python 2沒有yield from產生yield from ,但是您可以將該行替換為:

for u in list_flatten(item):
    yield u

如果您實際上不需要此列表,則可以這樣調用生成器:

for u in list_flatten(L):
    print(u)

產量

1
2
a
(3, 'b')
(5, 6)
11
22

您可以注意到,您需要的是:

  • 如果列表為空,則保持不變
  • 如果它只有一個元素並且該元素不是列表,則返回列表不變
  • 否則將第一個元素展平,將列表末尾展平並連接兩個子列表

在Python代碼中,它導致:

def flatten(L):
    if len(L) == 0: return L
    elif len(L) == 1 and not isinstance(L[0], list): return L
    else:
        return (flatten(L[0] if isinstance(L[0], list)
                else [L[0]]) + flatten(L[1:]))

它給出了預期的結果:

>>> L = [1, 2, 'a', (3, 'b'), (5, 6), ([11, 22],)]
>>> flatten(L)
[1, 2, 'a', (3, 'b'), (5, 6), ([11, 22],)]

暫無
暫無

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

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