您好我正在尝试将以下递归伪代码定义转换为R中的函数式编程构造:
a = [ random numbers between 0 and 10 ]
b = [ random numbers between -5 and 5 ]
c = [ random numbers between 0 and -10 ]
x0 = 200
index = 0
function f(x) {
index = index + 1
if( x is between 200 and 220 ) return f(x + a[index])
else if(x is between 220 and 250) return f(x + b[index])
else if(x is 250 and above) return f(x + c[index])
}
可执行R代码是:
a <- sample(1:10,size=50, replace=TRUE)
b <- sample(-5:5,size=50, replace=TRUE)
c <- sample(-1:-10,size=50, replace=TRUE)
index <- 0;
myfunc <- function(x){
index <<- index + 1;
if(index == 50) return(x)
if(x <= 220){ return(myfunc(x + a[index])) }
else if(x > 220 & x < 250){ return(myfunc(x + b[index])) }
else {return( myfunc(x + c[index]))}
}
print(myfunc(200));
想讨论任何方法,包括Map / Filter / Reduce或Vectorisation。非常感谢提前。
此外,如何保留50 x元素的整个路径(而不仅仅是查看x的一个答案)。
答案 0 :(得分:4)
您可以使用Reduce功能和accumulate选项来保存所有中间值。
要了解其工作原理,请尝试使用简单的“总和”功能
x = rep(200, 50)
Reduce(x=x, f=sum)
Reduce(x=x, f=sum, accumulate=T)
您正在寻找的答案需要您重写您的特殊功能,以便将其传递给Reduce:
foo <- function(x, y = 0){
if (200 <= x & x < 220){
x + sample(1:10, 1)
}
else if(220 <= x & x < 250){
x + sample(-5:5, 1)
}
else if (250 <= x){
x + sample(-1:-10, 1)
}
}
Reduce(x=rep(200, 50), f=foo, accumulate=T)
答案 1 :(得分:3)
我还没有把它变成一种功能形式,但我可以在R中做我认为你想要的东西:
x=200; index=0; while (index < 50) {index <- index + 1;
if(tail(x,1) <= 220){ x <-c(x, tail(x,1)+a[index]) } else
{ if(tail(x,1) & tail(x,1) < 250) { x <-c(x , tail(x,1)+b[index]) } else
{x <-c( x , tail(x,1)+c[index])} }
}
x
[1] 200 204 206 210 213 215 216 219 227 222 219 220 223 221 224 229 231 227 226 229 224 223 221 221
[25] 216 218 223 220 226 221 217 224 228 228 231 236 233 234 229 227 230 229 227 227 225 225 228 232
[49] 227 230 228
也许这有助于找到一种“功能化”它的方法。我认为Reduce
或replicate
或者参考类对象很有可能提供机制。这只是将x向量扩展1个元素,然后在下一次迭代时使用该元素来选择要使用的增量向量。如果你想要超过50长度输出,你可以使用模数余数数学作为索引。
答案 2 :(得分:2)
首先,我将首先参数化函数以匹配您的原始描述,并在模拟参数发生变化时更容易更改。
foo_cat <- function(x) {
if (200 <= x & x < 220) return("a")
if (220 <= x & x < 250) return("b")
if (250 <= x) return("c")
stop("x out of range")
}
ranges <- list(a = 1:10, b = -5:5, c = -(1:10))
foo_sample <- function(x, n = 1) {
sample(ranges[[foo_cat(x)]], n, rep = TRUE)
}
对我而言,这是函数式编程中最重要的部分:编写封装解决方案重要组件的函数。
接下来,我们将使用foo_sample
来解决for循环问题。这使得当前值和先前值之间的关系显式:
n <- 50
out <- c(200, rep(NA, n - 1))
for(i in seq(2, n)) {
out[i] <- out[i - 1] + foo_sample(out[i - 1])
}
接下来,您可以考虑删除for循环并将其替换为functional。不幸的是,没有内置函数来封装这个模式,所以你可以编写自己的函数(如果这是代码中非常常见的模式,这是一个好主意),或者坚持使用for循环(如果你想要一个好主意)你的代码易于阅读)。