其他迴圈構造同時重複
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
}