【问题标题】:Lazily transpose a list in Python在 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 上发帖。他/她是在寻求一种方法来做到这一点,而不是让我们审查和编辑他/她的代码。

标签: python python-3.x lazy-evaluation iterable


【解决方案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] )

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2017-07-13
    • 1970-01-01
    • 2012-04-09
    • 1970-01-01
    • 1970-01-01
    • 2010-11-11
    • 2010-09-26
    相关资源
    最近更新 更多