字符串压缩思路(用列表解析实现)

字符串压缩思路(用列表解析实现)(1)

python部落(python.freelycode.com)组织翻译,禁止转载,欢迎转发。

我喜欢Python的“zip”函数。我不确定我喜欢的“zip”究竟是干什么的,但我经常发现它是非常有用的。在我描述什么是“ZIP”之前,让我先给你举一个例子:

字符串压缩思路(用列表解析实现)(2)

正如你所看到的,“ZIP”的结果是一个元组序列。在Python 2中,你得到一个列表。在Python 3中,你得到了一个“zip对象”。索引为0的元组包含s[0]和t[0]。索引为1的元组包含s[1]和t[1]。等等。你可以对更多列表使用zip函数

字符串压缩思路(用列表解析实现)(3)

(你也可以对一个列表调用zip,从而返回了一大堆的包含一个元素的元组,但对我来说,似乎有点奇怪)

我通常使用zip来把平行的序列放到字典里,例如:

字符串压缩思路(用列表解析实现)(4)

由此,我们能够迅速而轻松地由两个平行序列制造一个字典

每当我在编程课中提到“zip”时,总会有人问如果一个参数比另一个参数短,会发生什么。简而言之,最短的获胜。

字符串压缩思路(用列表解析实现)(5)

如果你想让“zip”为较长的序列的每个元素返回一个元组,那就用“itertools”包里的“izip_longest”函数

现在,如果说有没有比zip更令我欣喜的特性,那就是列表解析。上周,当我的一个学生问我们能不能使用列表解析实现“zip”,我甚至等不及想要立即试试。

所以,我们是怎么做的呢?

首先,我们假设我们有两个等长的序列,s(字符串)和t(元组),我们想要获取一个有三个元组的列表,一个方法是如下:

字符串压缩思路(用列表解析实现)(6)

说实话,这个效果很好,但我们仍有一些改善的方法。

首先是,如果我们能让列表解析实现的“zip”能够处理不同大小的输入,那就美滋滋了。意思是说:不是用range(len(s)),而用range(len(x)),其中x是较短的序列。我们能够通过内建函数“sorted”来实现:让其通过序列长度来从小到大排序,例如:

字符串压缩思路(用列表解析实现)(7)

在上面的代码中,我创建一个新的元组(s,t),并把它作为“sorted”的第一个参数。鉴于这些输入,我们将从“sorted”得到一个返回的列表。因为我们使用内置的“len”函数作为“key”参数,如果s更短,“sorted”将返回[s,t], 如果t更短,将返回 [t,s]。这意味着,在索引0的元素保证不会长于任何其他序列。(如果所有的序列大小相同,那么我们不关心哪一个返回给我们。)

把这些都一起放入我们的解析中,我们得到:

字符串压缩思路(用列表解析实现)(8)

这对于一个简单的列表解析来说稍微有点复杂,所以我将把第二行的部分分成一个函数,这仅仅是为了把上面那个东西整理的清楚一点

字符串压缩思路(用列表解析实现)(9)

如今,我们的函数有*args,意味着它可以接受任何数量的序列,序列按长度排序,此时最短的那个序列被传递给“len”,而结果将被传给“range”。

因此,如果最短的序列是“abc”,我们最终返回range(3),可以索引0,1,和2 --完美的符合我们的需要。

现在,还有一件事要做,使它更接近真正的“zip”:正如我刚才提到的,Python 2的“zip”返回一个列表,但Python 3的“zip”返回一个迭代器对象。这意味着,我们不会一次返回全部元组,即使产生的列表非常长,也不会占用许多内存。我们能对我们的列表解析这么做吗?

是的,但如果我们使用列表解析,它总是返回一个列表。相比之下,如果我们使用一个生成器表达式,我们将得到一个迭代器返回,而不是整个列表。幸运的是,创建这样一个生成器表达式只不过是用一个生成器表达式代替(我们)的列表解析:

字符串压缩思路(用列表解析实现)(10)

然后现在就万事大吉啦!我们欢迎更好的改进的点子,不过对于一个同时喜欢“zip”和列表解析的人而言,把两者联系在一起是很有趣的。

英文原文:http://blog.lerner.co.il/implementing-zip-list-comprehensions/ 译者:孙明宏,

免责声明:本文仅代表文章作者的个人观点,与本站无关。其原创性、真实性以及文中陈述文字和内容未经本站证实,对本文以及其中全部或者部分内容文字的真实性、完整性和原创性本站不作任何保证或承诺,请读者仅作参考,并自行核实相关内容。文章投诉邮箱:anhduc.ph@yahoo.com

    分享
    投诉
    首页