繁体   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