在 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 已经做了这种缓冲,所以不需要自己实现。

唯一的其他(次要)事情是我会稍微不同地写它,避免使用maplambdas:

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 中懒惰地转置一个列表的主要内容,如果未能解决你的问题,请参考以下文章

如何有效地转置非方阵?

有没有一种方法可以简单地转置 SQL 中的表。此表包含 Numeric 和 Varchar 值

Python,转置列表并写入 CSV 文件

如何使用情节提要正确地转到嵌入式选项卡栏和导航控制器?

Python将不一致的列表转置/转换为DataFrame

Python代码阅读(第41篇):矩阵转置