【问题标题】:How to add Results into a Vector within a Loop in R如何将结果添加到 R 中循环内的向量中
【发布时间】:2021-03-11 21:26:44
【问题描述】:

我被提示了一个问题,并且非常接近解决我需要的问题。问题如下-

“编写一个 while 循环,计算任何非负整数 mynum 的阶乘并将其存储为一个新对象,方法是在每次重复大括号代码时将 mynum 减 1。”

另一个因素是,如果输入 0 或 1,则输出将为 1。

我写的代码如下-

factorialcalc <- function(i){
  factorial <- 1
  if(i==0 | i==1){
    factorial <- 1
  } else{
    while(i >= 1){
      factorial <- factorial * i
      i <- i-1
    }
  }
  return (factorial)
}

有输入-

mynum <- 5
factorialcalc(mynum)

和输出-

[1] 120

您可能想知道,“您的代码运行良好,那么问题出在哪里?” 我的问题在于问题的“计算和存储”部分。

如何修改我的代码以将 factorialcalc 的答案放入向量中?

示例- 我输入

mynum <- 5
factorialcalc(mynum)

mynum <- 3
factorialcalc(mynum)

mynum <- 4
factorialcalc(mynum)

当我调用这个新向量时,我希望看到一个包含所有三个输出的向量 (就像我制作了一个向量 c(120,6,24))

我在想有一种方法可以在我的函数或 while 循环中的某处添加这个向量,但我不确定在哪里。另外,请注意答案必须包含我的代码中的循环。

我要寻找的答案是一个空向量,比如answers &lt;- c(),每次我要运行函数factorialcalc,在函数期间,我都会将factorial的返回结果添加到这个新的answers 向量。

我试过放这样的东西-

factorialcalc <- function(i){
  factorial <- 1
  answers <- c()
  answers[i] <- answers[factorial]
  if(i==0 | i==1){
    factorial <- 1
  } else{
    while(i >= 1){
      factorial <- factorial * i
      i <- i-1
    }
  }
  return (factorial)
}

这似乎行不通,但我认为这个想法是存在的。

提前感谢您的帮助。

【问题讨论】:

  • 如果您在for 循环之前初始化一个空向量,您可以简单地在循环中附加一个新值。例如myvec &lt;- numeric(); for... myvec &lt;- c(myvec, newval)... length 我的 myvec 将随着循环的每次迭代而增长。
  • 这仅适用于for 循环吗?给我的问题是使用while 循环来做到这一点
  • 使用可以使用任何循环的方法。您还可以使用该方法来扩充对象列表。例如创建列表:mylist &lt;- list() 并在循环内增加列表索引:mylist[[i]] &lt;- newdf 其中i 是整数循环索引值。
  • 这个问题和你之前的问题stackoverflow.com/questions/65057122/…有什么不同吗?

标签: r function if-statement while-loop factorial


【解决方案1】:

这是一个说明如何为阶乘函数构建结果向量的解决方案。我们使用testthat 包为函数构建单元测试。

我们不是从i向下迭代到1,而是从2迭代到i,使用输出向量中的j-1值乘以for()循环中的当前数字。

我们还在函数顶部包含错误检查。由于 R 没有办法直接将数值向量验证为整数/整数,因此我们将输入的绝对值减去其舍入值与机器精度进行比较,如果比较失败则停止。

factorial <- function(i){
     # return a vector of factorial values from 1 to i, where
     # i represents the i-th value in the factorial series 
     
     # first, validate the input 
     if(!is.numeric(i)) stop("i must be a whole number")
     if(!(abs(i - round(i)) < .Machine$double.eps^0.5)) stop("i must be a whole number")
     if (i < 0) stop("i must be a whole number")

     # now, process based on value of i 
     if (i %in% c(0,1)) return(1)
     resultVector <- 1
     # if we get here, i is greater than 1
     for(j in 2:i) resultVector <- c(resultVector,resultVector[j-1]*j)
     resultVector
}

我们使用各种测试来测试函数,从无效输入处理到使用已知值确认函数的输出。我们还将输出向量的长度与i的输入值进行比较。

library(testthat)
test_that("Factorial function works",{
     expect_error(factorial(-3),"i must be a whole number",ignore.case=TRUE)
     expect_equal(1,factorial(0))
     expect_equal(1,factorial(1))
     expect_equal(c(1,2),factorial(2))
     expect_equal(c(1,2,6),factorial(3))
     expect_equal(c(1,2,6,24),factorial(4))
     expect_equal(c(1,2,6,24,120),factorial(5))
     expect_equal(5,length(factorial(5))) # test that length matches input i
     expect_error(factorial(3.1),"i must be a whole number",ignore.case=TRUE)
     expect_error(factorial("zzz"),"i must be a whole number",ignore.case=TRUE)
     
     
})

...以及测试结果:

==> Testing R file using 'testthat'

✓ |  OK F W S | Context
✓ |  10       | factorial

══ Results ═════════════════════════════════════════════════════════════════════
Duration: 0.2 s

OK:       10
Failed:   0
Warnings: 0
Skipped:  0

Test complete

最后,我们多次运行这个函数来说明它的输出:

> lapply(1:8,factorial)
[[1]]
[1] 1

[[2]]
[1] 1 2

[[3]]
[1] 1 2 6

[[4]]
[1]  1  2  6 24

[[5]]
[1]   1   2   6  24 120

[[6]]
[1]   1   2   6  24 120 720

[[7]]
[1]    1    2    6   24  120  720 5040

[[8]]
[1]     1     2     6    24   120   720  5040 40320

【讨论】:

    【解决方案2】:

    首先考虑将Reduce 替换为您的方法:

    Reduce(`*`, 1:5)
    # [1] 120
    

    要增量扩展,请在 apply 函数中传递带有 Reduce 的序列(由于多个元素,只有 mapply 需要调整):

    factorialcalc <- function(i) Reduce(`*`, 1:i)
        
    sapply(1:5, factorialcalc)
    # [1]   1   2   6  24 120
    
    vapply(1:5, factorialcalc, integer(1))
    # [1]   1   2   6  24 120
    
    tapply(1:5, 1:5, factorialcalc)
    #   1   2   3   4   5 
    #   1   2   6  24 120 
        
    factorialcalc <- function(i,j) Reduce(`*`, i:j)
    mapply(factorialcalc, 1, 1:5)
    # [1]   1   2   6  24 120    
    

    【讨论】:

      猜你喜欢
      • 2015-11-28
      • 2019-04-09
      • 2021-01-03
      • 1970-01-01
      • 2015-03-22
      • 1970-01-01
      • 2021-10-10
      • 2021-02-18
      • 2013-03-04
      相关资源
      最近更新 更多