其他循环构造同时重复
R 提供了两个额外的循环结构 while 和 repeat,它们通常用于需要迭代次数不确定的情况。
while 循环
while 循环的一般形式如下,
while (condition) {
## do something
## in loop body
}
其中 condition 在进入循环体之前进行评估。如果 condition 计算为 TRUE,则循环体内的代码被执行,并且该过程重复直到 condition 计算为 FALSE(或达到 break 语句;见下文)。与 for 循环不同,如果 while 循环使用变量执行增量迭代,则必须提前声明和初始化变量,并且必须在循环体内更新。例如,以下循环完成相同的任务:
for (i in 0:4) {
cat(i, "\n")
}
# 0
# 1
# 2
# 3
# 4
i <- 0
while (i < 5) {
cat(i, "\n")
i <- i + 1
}
# 0
# 1
# 2
# 3
# 4
在上面的 while 循环中,线 i <- i + 1 是防止无限循环所必需的。
另外,可以通过从循环体内部调用 break 来终止 while 循环:
iter <- 0
while (TRUE) {
if (runif(1) < 0.25) {
break
} else {
iter <- iter + 1
}
}
iter
#[1] 4
在这个例子中,condition 总是 TRUE,所以终止循环的唯一方法是在体内调用 break。请注意,iter 的最终值将取决于运行此示例时 PRNG 的状态,并且每次执行代码时(基本上)应产生不同的结果。
repeat 循环
repeat 构造与 while (TRUE) { ## something } 基本相同,具有以下形式:
repeat ({
## do something
## in loop body
})
额外的 {} 不是必需的,但是 () 是。使用 repeat 重写上一个例子,
iter <- 0
repeat ({
if (runif(1) < 0.25) {
break
} else {
iter <- iter + 1
}
})
iter
#[1] 2
更多关于 break
重要的是要注意 break 只会终止直接封闭的循环。也就是说,以下是无限循环:
while (TRUE) {
while (TRUE) {
cat("inner loop\n")
break
}
cat("outer loop\n")
}
但是,通过一点创造力,可以完全从嵌套循环中完全破坏。作为示例,请考虑以下表达式,在其当前状态下,将无限循环:
while (TRUE) {
cat("outer loop body\n")
while (TRUE) {
cat("inner loop body\n")
x <- runif(1)
if (x < .3) {
break
} else {
cat(sprintf("x is %.5f\n", x))
}
}
}
一种可能性是认识到,与 break 不同,return 表达式确实具有跨多个封闭环循环返回控制的能力。但是,由于 return 仅在函数内使用时才有效,我们不能简单地用 return() 替换 break,而是需要将整个表达式包装为匿名函数:
(function() {
while (TRUE) {
cat("outer loop body\n")
while (TRUE) {
cat("inner loop body\n")
x <- runif(1)
if (x < .3) {
return()
} else {
cat(sprintf("x is %.5f\n", x))
}
}
}
})()
或者,我们可以在表达式之前创建一个虚拟变量(exit),并在我们准备终止时通过 <<- 从内部循环激活它:
exit <- FALSE
while (TRUE) {
cat("outer loop body\n")
while (TRUE) {
cat("inner loop body\n")
x <- runif(1)
if (x < .3) {
exit <<- TRUE
break
} else {
cat(sprintf("x is %.5f\n", x))
}
}
if (exit) break
}