繁体   English   中英

从 R 中的递归 function 编译向量

[英]Compiling a vector from a recursive function in R

我试图了解作用域如何在 R 中的递归函数中工作。

上下文是这个 function 应该返回向量元素的所有唯一组合。 (确切所需的 output 的详细信息在这里并不真正相关。)

perm <- function(x) {
    n <- length(x)
    if (n == 1) {
        print(x)
    } else {
        y <- NULL
        for (i in 1:n) {
            y <- paste(x[i], perm(x[-i]), sep = "_")
        }
        print(y)
    }
}

当我打印我知道要返回的对象(此处为print(x)print(y) )时,我得到正确的值返回到控制台,就像打印 output 一样:

perm(c("a","b","c"))

但是,当我尝试将这些收集到一个向量中时,生成的向量包含的元素比打印的要多许多数量级。 我怀疑这与递归有关,但考虑到print功能只是被明智地触发,这似乎很奇怪。 例如,使用全局变量跟踪 output 以忽略任何范围问题:

out <- c()
perm <- function(x) {
    n <- length(x)
    if (n == 1) {
        assign('out', c(out, x), envir = .GlobalEnv)
    } else {
        y <- NULL
        for (i in 1:n) {
            y <- paste(x[i], perm(x[-i]), sep = "_")
        }
        assign('out', c(out, y), envir = .GlobalEnv)
    }
}

perm(c("a","b","c"))
out

第一个示例仅打印十个值,而在第二个示例中, out的长度为 56,并且包含在第一个示例中找不到的值(例如, "c_c" )。 我知道以这种方式分配向量效率非常低,但我只是想弄清楚范围如何工作以及为什么这些结果如此不同。 我不会想到print function 会有任何范围界定问题,即每次触发print(x)print(y)时,我都希望 output 打印到控制台。

当我将out分配给父框架而不是全局环境时,也会发生同样的事情,即out <<- c(out, x) 有趣的是,如果我只使用print语法,我可以轻松计算大量组合; 但是当使用向量赋值时,超过四个元素的任何东西都会导致递归混乱,从而破坏系统。

所以我想问题是,

  1. 为什么当它们在同一个地方被调用时, print function 似乎更频繁地触发向量分配?

  2. 有没有更好的方法来实现这种 function?

perm function 基于此博客文章中的功能之一。

  1. 为什么当它们在同一个地方被调用时,打印 function 似乎更频繁地触发向量分配?

问题是print返回第一个参数,而assign返回分配的值。 拿:

b <- assign("a", 2)
b
#R> [1] 2

因此,您的 function 应该是:

out <- c()
perm <- function(x) {
  n <- length(x)
  if (n == 1) {
    assign('out', c(out, x), envir = .GlobalEnv)
    x
  } else {
    y <- NULL
    for (i in 1:n) {
      y <- paste(x[i], perm(x[-i]), sep = "_")
    }
    assign('out', c(out, y), envir = .GlobalEnv)
    y
  }
}

perm(c("a","b","c"))
#R> [1] [1] "c_b_a"
out
#R> [1] "c"     "b"     "c_b"   "c"     "a"     "c_a"   "b"     "a"     "b_a"   "c_b_a"

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM