在 Python 中懒惰地转置一个列表
Posted
技术标签:
【中文标题】在 Python 中懒惰地转置一个列表【英文标题】:Lazily transpose a list in Python 【发布时间】:2014-05-31 22:28:16 【问题描述】:所以,我有一个 3 元组的可迭代对象,它是惰性生成的。我试图弄清楚如何将其转换为 3 个可迭代对象,分别由元组的第一个、第二个和第三个元素组成。不过,我希望这是懒惰的。
例如,我希望将[(1, 2, 3), (4, 5, 6), (7, 8, 9)]
变成[1, 4, 7]
、[2, 5, 8]
、[3, 6, 9]
。 (除了我想要迭代而不是列表。)
标准的zip(*data)
成语不起作用,因为参数解包扩展了整个可迭代对象。 (您可以通过注意 zip(*((x, x+1, x+2) for x in itertools.count(step=3)))
挂起来验证这一点。)
到目前为止,我想出的最好的方法如下:
def transpose(iterable_of_three_tuples):
teed = itertools.tee(iterable_of_three_tuples, 3)
return map(lambda e: e[0], teed[0]), map(lambda e: e[1], teed[1]), map(lambda e: e[2], teed[2])
这似乎有效。但它看起来不像是干净的代码。它还做了很多看似不必要的工作。
【问题讨论】:
izip
来自 itertools
模块?
既然你有工作代码,你可能会从代码审查中得到更好的结果
你如何期望你的新迭代器从第三个元组中得到7
而不消耗整个外部迭代?如果您在像count
这样的无限迭代器上尝试,您的tranpose
也会挂起。
如果您包含一个您打算如何使用它的示例,将会有所帮助。也许我们可以提出一个更好的方法
@wnnmaw 不,可以在 SO 上发帖。他/她是在寻求一种方法来做到这一点,而不是让我们审查和编辑他/她的代码。
【参考方案1】:
您的transpose
正是您所需要的。
对于您选择的任何解决方案,您都必须缓冲未使用的值(例如,要获取 7,您必须读取 1-6,并将它们存储在内存中以供其他迭代请求它们时使用) . tee
已经做了这种缓冲,所以不需要自己实现。
唯一的其他(次要)事情是我会稍微不同地写它,避免使用map
和lambda
s:
def transpose(iterable_of_three_tuples):
teed = itertools.tee(iterable_of_three_tuples, 3)
return ( e[0] for e in teed[0] ), ( e[1] for e in teed[1] ), ( e[2] for e in teed[2] )
【讨论】:
以上是关于在 Python 中懒惰地转置一个列表的主要内容,如果未能解决你的问题,请参考以下文章