【问题标题】:Combining recursion with map - is reduce the solution?将递归与地图相结合 - 是减少解决方案吗?
【发布时间】:2022-02-04 11:09:53
【问题描述】:

在此示例中,我试图不惜一切代价避免使用 for 循环。考虑这个简单的案例:

我有一个向量z 和一个初始条件b1

z <- 1:5
b1 <- 0

考虑一下这个简单的函数,比如添加:

f <- function(y, b){
 return(y + b)
}

我想编写一个生成序列S 的函数,如下所示:第一个元素,称为S[1]f 的输出,y 参数为z[1],@ 987654330@ 参数作为初始条件b1。第二个元素S[2] 就是S[2] = f(y = z[2], b = S[1])。我该怎么办?

请记住,我不想使用像 cumsum 这样的东西,因为我的实际函数 f 更复杂 在这种情况下,所需的输出将是向量:

c(0 + 1,
1 + 2,
3 + 3,
6 + 4,
10 + 5)

c(1, 3, 6, 10, 15)

我考虑过使用reduce,但我猜它只接受与递归参数b 而不是映射部分y 的交易

【问题讨论】:

  • 为什么要避免for 循环“不惜一切代价”?正确完成后,for 循环是明确的、清晰的,并且与某些类似 apply 的解决方案一样快(如果不是更快的话)。
  • @r2evans 只是为了简洁
  • @r2evans 我猜是为了学习
  • @Ben 你是对的,我会纠正这个
  • @r2evans 刚刚更正了它

标签: r loops recursion purrr


【解决方案1】:
Reduce(function(prev, this) prev + this,
       1:5, init=0, accumulate=TRUE)[-1]
# [1]  1  3  6 10 15

你可以很容易地使用你自己的函数来代替我的匿名函数,我这样定义它来演示哪个值是哪个:第一个参数是你的S[n-1],第二个是你的z[n]

[-1] 是因为这个:没有init=,第一个函数调用实际上是f(prev=z[1], this=z[2]),只有当你的b1 为0 时才正确。如果@987654329 @ 是其他任何东西,那么你必须使用init=b1。但是,当使用init= 时,它有效地 将其添加到输入向量(您的z)之前。这意味着对函数的第一次调用是f(prev=b1, this=z[1]),这是正确的,但这也意味着返回值包含 b1,因此太长了。幸运的是,我们可以很容易地删除第一个元素。

最后,Reduce 的正常操作是只返回最后一次调用函数的值(因此Reducereduction 概念);使用accumulate= 真的意味着Reduce 是一个累积运算函数。

【讨论】:

  • 谢谢!如果我的函数具有跨迭代不变的其他参数,这是否有效?我怎么能改变呢?
  • 我不确定你到底是什么意思。 anon-func 必须接受至少两个参数,其中任何超过第二个的参数要么需要具有默认值,要么可以是missing(.)。如果您需要任何非前两个参数来改变,那么您需要更多的东西。为此,我建议尝试调整可能支持您需要的recent answer of mine
  • 在我的情况下它们可以保持不变。 missing(.) 是什么意思?把它们留空?
  • 如果它们可以是常量,那么函数的前两个参数将被Reduce 使用,任何其他参数都必须依赖于它们的默认值。如果它们需要设置(为静态值),那么如果你的这个函数被称为func,那么你需要一个包装器:Reduce(function(pr, th) func(pr, th, arg1=9, arg2=42), 1:5, init=0, accumulate=TRUE)[-1]。这有意义吗?
猜你喜欢
  • 1970-01-01
  • 2020-06-07
  • 2019-06-26
  • 1970-01-01
  • 2013-07-22
  • 1970-01-01
  • 1970-01-01
  • 2015-10-25
  • 1970-01-01
相关资源
最近更新 更多