簡體   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