其他循环构造同时重复
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
}