簡體   English   中英

為什么zip(*)無法恢復我的原始列表

[英]Why is zip(*) not restoring my original list

我試圖了解正在發生的事情:

a = list('hello world')
b = [a[i::l]for i in range(8)]

然后,我期望:

zip(*b) == a

但是我得到以下內容:

 [('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o')]

也許我不了解zip(*)的含義,但是我認為它解壓縮了一個列表列表,並從中列出了一個列表。 我要去哪里錯了?

您錯過了zip()的詳細信息,如文檔所述

當最短的輸入可迭代數用盡時,迭代器停止

hello world有11個字符(質數),因此,除了具有每個字符的11個獨立序列的列表之外,如果沒有至少一個較短的列表,則無法生成列表列表。

例如,如果我們假定l = 8 (大於等於5的任何值都會產生您顯示的輸出),則將a設置為:

[['h', 'r'], ['e', 'l'], ['l', 'd'], ['l'], ['o'], [' '], ['w'], ['o']]

那是8個列表,第一個包含2個元素,其余的只有一個。 因此,只有這些元素中的第一個元素才可以用來產生組合:

>>> [l[0] for l in b]
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o']

您只循環了8次,因此b只有8個頂級列表可以接收字母。 對於l 5或更大的值,您將獲得剩余字母的不同分布,但是僅剩余3個字符,就沒有很多方法可以在列表中分配剩余字母,而l小於8 ,您只需添加重復的字母(因為對於等於或小於7的任何l[0::l][7::l]都保證重疊)。

您必須循環最多11次,並每11個字符使用一次,才能得到可以壓縮到相同序列的內容:

>>> b = [a[i::11]for i in range(11)]
>>> b
[['h'], ['e'], ['l'], ['l'], ['o'], [' '], ['w'], ['o'], ['r'], ['l'], ['d']]
>>> list(zip(*b))
[('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o', 'r', 'l', 'd')]

這仍然是不一樣的a ,因為zip()產生序列的序列(這里只有一個,因為只有在每個嵌套列表中的單個值)。 您可以使用next()獲得第一個(也是唯一一個)元素:

>>> a == list(next(zip(*b)))
True

您可以改為使用itertools.zip_longest()繼續迭代,直到用完最長的可迭代輸入為止,並添加默認填充值以增強較短的序列。 如果您想再次將序列連接回到整個字符串,則可以使用空字符串:

try:
    # Python 3
    from itertools import zip_longest
except ImportError:
    # Python 2 has the same object, but with i prefixed
    from itertools import izip_longest as zip_longest

result = list(zip_longest(*b, fillvalue=''))

但是,這將產生兩個元組。 畢竟,輸入中有兩列:

>>> from itertools import zip_longest
>>> b = [a[i::8]for i in range(8)]
>>> list(zip_longest(*b, fillvalue=''))
[('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o'), ('r', 'l', 'd', '', '', '', '', '')]

您必須將它們鏈接起來以重新組合它們; itertools.chain.from_iterable()可以做到這一點:

>>> from itertools import chain
>>> ''.join(chain.from_iterable(zip_longest(*b, fillvalue='')))
'hello world'

這僅適用於l = 8 ,再次,因為重疊的切片為較低值的l ,對於l > 8 ,你開始缺少從端字符作為沒有8的a[i::l]片包括這些字符

>>> for l in range(2, 12):
...     print(f'{l:>2d}:', ''.join(chain.from_iterable(zip_longest(*[a[i::l] for i in range(8)], fillvalue=''))))
...
 2: hello wollo worlo worldworldrldd
 3: hello wolo worldworldld
 4: hello woo worldrld
 5: hello wo worldd
 6: hello woworld
 7: hello woorld
 8: hello world
 9: hello wold
10: hello wod
11: hello wo

您的代碼不清楚,我們也不知道l到底是什么! 如果您按原樣運行它,您肯定會得到一條錯誤消息,說明未定義l。

但是,對於zip函數,它會在最短的迭代器處停止,要使其繼續運行,您應該使用zip_longest

有關zip函數如何工作的更多詳細信息,請檢查以下內容: Python zip

暫無
暫無

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

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