[英]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.