如何将while循环的结果存储在列表中?

时间:2014-01-19 14:23:21

标签: r while-loop

我知道这是一个非常基本的问题,但我认为我的语法有问题。 我正在做一个while循环,我想稍后使用结果。但是,我不知道如何将结果存储在列表中。

这是我想要做的while循环的“简短版本”。

z <- 0
 while(z < 10) { 
    z <- z + 1
    print(z)  
 }

如何将此while循环的结果存储在列表中?

谢谢!

4 个答案:

答案 0 :(得分:4)

R答案都令人失望,因为他们使用了可怕的“复制和追加”模式,这是Patrick Burn R Inferno的第二章。问题在于,当向量被迫增长时,这会产生n *(n-1)/ 2个元素副本。第一个改进是预先分配和填充,第二个是让R用lapply(列表)或vapply(向量)为你管理事物,第三个是使用实现所需操作的“向量化”函数。

以下是一些不好的实现

f1 <- function(n) {
    ## BAD, copy and append
    res <- c()
    for (i in seq_len(n))
        res <- c(res, i)
   res
}
f2 <- function(n) {
    ## BAD, copy and append
    res <- c()
    for (i in seq_len(n))
        res[[i]] <- i
    res
}
f3 <- function(n) {
    ## BAD copy and append
    res <- c()
    i <- 0
    while (i < n) {
        i <- i + 1
        res <- c(res, i)
    }
}

更好的实现仍然需要用户管理结果

f4 <- function(n) {
    ## better, pre-allocate and fill
    res <- integer(n)
    for (i in seq_len(n))
        res[[i]] <- i
    res
}

然后允许R完成所有工作的实现

f5 <- function(n)
    ## better, lapply manages allocation
    sapply(seq_len(n), function(i) i)
f6 <- function(n)
    ## better, vapply manages allocation and enforces return type
    vapply(seq_len(n), function(i) i, integer(1))

以下是一些时间

library(microbenchmark)
n <- 100
microbenchmark(f1(n), f2(n), f3(n), f4(n), f5(n), f6(n))
## Unit: microseconds
##   expr     min       lq   median       uq     max neval
##  f1(n)  68.857  74.3045  75.5995  76.6050  87.270   100
##  f2(n) 180.174 185.1460 187.1960 191.0030 221.571   100
##  f3(n) 141.022 146.0605 148.0615 151.0435 184.322   100
##  f4(n) 116.976 122.0740 124.8700 127.4540 166.803   100
##  f5(n) 214.319 219.9760 223.4540 227.5000 294.203   100
##  f6(n)  91.871  94.3685  95.4235  96.8335 126.893   100
n <- 10000
microbenchmark(f1(n), f2(n), f3(n), f4(n), f5(n), f6(n), times=10)
## Unit: milliseconds
##   expr        min         lq     median         uq        max neval
##  f1(n) 226.239815 227.871791 229.115319 232.963898 274.052546    10
##  f2(n) 134.979884 135.509744 136.726051 137.707050 152.690075    10
##  f3(n) 185.598667 187.437479 189.442674 210.786491 333.767094    10
##  f4(n)  11.523032  11.676948  11.777627  11.864006  12.099091    10
##  f5(n)  14.670557  14.808911  15.041665  15.158167  15.675638    10
##  f6(n)   8.295519   8.401100   8.424139   8.525598  10.374145    10

对于这个特殊的例子,当然有一个“矢量化”的解决方案仍然更快

microbenchmark(f6(n), seq_len(n), times=10)
## Unit: microseconds
##        expr      min        lq    median       uq       max neval
##       f6(n) 8240.384 9518.9940 9561.2310 9649.877 11427.134   100
##  seq_len(n)   20.624   20.9535   22.0295   22.892    34.461   100

答案 1 :(得分:1)

listy <- list()
z <- 0
while(z < 10) { 
z <- z + 1
listy[z]  <- z 

print(z)  
}
> listy
[[1]]
[1] 1

[[2]]
[1] 2

[[3]]
[1] 3

[[4]]
[1] 4

[[5]]
[1] 5

[[6]]
[1] 6

[[7]]
 [1] 7

[[8]]
[1] 8

[[9]]
[1] 9

[[10]]
[1] 10

答案 2 :(得分:-1)

也许这有帮助

z <- 0 
res <- c()
while(z<10) { 
    z <- z+1
    res <- c(res, z)
}

结果是矢量,而不是列表。而这种实施效率非常低。 如果您知道迭代次数,那么预分配就像@Dason和@Martin Morgan所指出的那样。

答案 3 :(得分:-1)

你在用哪种语言编写?

Java示例:

int List<String> = new List<>();

while(z < 10) { List.add(z); z++ }