我正试图了解正在发生的事情:
a = list('hello world')
b = [a[i::l]for i in range(8)]
然后我会期望:
zip(*b) == a
但是我得到的是以下内容:
[('h', 'e', 'l', 'l', 'o', ' ', 'w', 'o')]
也许我无法理解zip(*)的作用,但是我认为它解压缩了一个列表列表,并从中列出了一个列表。我要去哪里错了?
答案 0 :(得分:2)
您错过了zip()
的详细信息,如outlined in the documentation:
最短的可迭代输入耗尽时,迭代器停止
hello world
中有11个字符,一个质数,因此,除了11个单独序列的列表(每个序列都有一个字符)之外,如果没有至少一个较短的列表,则无法生成列表列表
例如,如果我们假设l = 8
(大于等于5的任何值都会产生您显示的输出),那么a
设置为:
[['h', 'r'], ['e', 'l'], ['l', 'd'], ['l'], ['o'], [' '], ['w'], ['o']]
共有8个列表,其中第一个包含2个元素,其余的只有一个。因此,只有这些元素的 first元素用于生成组合:
>>> [l[0] for l in b]
['h', 'e', 'l', 'l', 'o', ' ', 'w', 'o']
您只循环了8次,因此b
中只有8个顶级列表可以接收信件。对于l
的5或更高的不同值,您将得到剩余字母的不同分布,但是仅剩余3个字符,就没有很多方法可以将剩余的字母分布在整个列表中,而{{ 1}}在l
下方,您只需添加重复的字母(因为8
和[0::l]
对于等于或小于7的任何[7::l]
都可以重叠)。
您必须最多循环11次,并每11个字符使用一次,即可获得将压缩到相同序列的内容:
l
这仍然与>>> 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()
您可以改为使用itertools.zip_longest()
来继续迭代,直到用完最长可输入的 为止,并添加默认的填充值以增加较短的序列。如果您想再次将序列重新连接回整个字符串,则可以使用空字符串:
>>> a == list(next(zip(*b)))
True
这会生成两个元组;毕竟输入中有两列:
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=''))
您必须将它们链接起来以重新组合它们; itertools.chain.from_iterable()
可以做到:
>>> 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', '', '', '', '', '')]
这再次仅适用于>>> from itertools import chain
>>> ''.join(chain.from_iterable(zip_longest(*b, fillvalue='')))
'hello world'
,这是因为l = 8
的较低值的切片重叠,对于l
,您从头开始缺少了8个{ {1}}个切片包括这些字符
l > 8
答案 1 :(得分:0)
您的代码不清楚,我们也不知道l
到底是什么!如果您按原样运行它,您肯定会收到一条错误消息,说明未定义l。
但是,对于zip函数,它在最短的迭代器处停止,要使其继续运行,您应该使用zip_longest
。
有关zip功能如何工作的更多详细信息,请检查以下内容:Python zip