【问题标题】:Python: Functionally Merging Two Iterators Where One is RecursivePython:在功能上合并两个迭代器,其中一个是递归的
【发布时间】:2016-02-09 13:54:51
【问题描述】:

相关问题How do I merge two python iterators? 适用于两个独立的迭代器。但是,我无法找到或想到合并两个迭代器所需的工具,其中一个迭代器是递归的,另一个作为输入。我有迭代器stuff,这是一个简单的列表。然后我有迭代器theta,它接受一个函数func 并产生x、func(x)、func(func(x)),其中func 的输入之一是stuff 的一个元素。我用可变状态解决了这个问题,如下所示:

theta = some_initial_theta
for thing in stuff:
    theta = update_theta(theta, thing)
return theta

这种格式的具体例子:

def update_theta(theta, thing):
    return thing * 2 + theta

stuff = [100, 200, 300, 400]


def my_iteration():
    theta = 0
    for thing in stuff:
        theta = update_theta(theta, thing)
    print(theta)
# This prints 2000

我确信在没有可变状态和 for 循环的情况下,有一种优雅的方法可以做到这一点。一个简单的 zip 不适合我,因为 theta 迭代器使用它的前一个元素作为下一个元素的输入。

表达 theta 的一种优雅方式是使用 more_itertools package 中提供的 iterate 方法:

iterate(lambda theta: update_theta(theta, thing), some_initial_theta)

但是,问题在于thing 将在整个迭代过程中得到修复。可以通过传入整个列表 stuff 来处理这个问题,然后从 update_theta 方法返回它的其余部分:

iterate(lambda theta: update_theta(theta[0], theta[1]), (some_initial_theta, stuff))

但是,我真的不想修改update_theta 方法来获取它不感兴趣的整个列表并处理返回该列表尾部的机制。虽然它在编程上并不困难,但它的关注点分离很差。 update_theta 不应该知道或关心整个列表 stuff

【问题讨论】:

  • 您能否提供一个简单的自包含示例来说明您在说什么(例如,以您所描述的方式运行的简单迭代器的实际示例)?
  • @BrenBarn 我添加了一个具体的例子。
  • reduce
  • @PeterWood 你将如何处理在reduce 的每一步中获取列表stuff 的新元素?
  • 我真的看不出你的做法有什么问题。同样从您的示例中,您似乎正在尝试将两个迭代器组合起来以获得单个结果(不是中间结果的可迭代),这与您链接到的问题有些不同,并且意味着发生的事情的详细信息获得该结果的方法可能不太重要。

标签: python recursion functional-programming iterator generator


【解决方案1】:

正如 Peter Wood 在 cmets 中所建议的,这正是内置函数 reduce 所做的:

result = reduce(update_theta, stuff, some_initial_theta)

在 Python 3 中,reduce 已移动到 functools.reduce,因此您需要将其导入:

from functools import reduce

如果你想要一个所有中间值的迭代器,Python 3 提供了itertools.accumulate。没有指定初始值的参数,因此您需要将初始值放入迭代器中:

from itertools import accumulate, chain
result_iterator = accumulate(chain([some_initial_theta], stuff), update_theta)

Python 2 没有itertools.accumulate,但您可以从 Python 3 文档中复制等效代码。没有简单的方法可以根据 Python 2 标准工具来制定它,这就是为什么人们首先希望将它添加到 Python 3 中。

【讨论】:

  • 谢谢!我需要再测试一下reduce。我认为之前 reduce 让我感到困惑的是它只处理 2 个参数。就像 x + y 中的 x 和 y,而我的 update_theta() 需要很多参数。我认为我需要做的是定义一个保持所有其他参数不变的 lambda,然后像单个参数函数一样简单地将它与 reduce 一起使用。
  • 我回到这个问题的速度很慢,但我相信你的解决方案是正确的,所以我会继续给你信任。我只需要使用 lambda 将其减少为两个参数。
猜你喜欢
  • 1970-01-01
  • 2017-06-25
  • 2021-10-05
  • 2014-10-16
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
相关资源
最近更新 更多