12 懶人的最愛:while 迴圈

一個 while 迴圈的外觀架構長得像這樣子:

while (某種條件){
    # 每次迭代要執行的程式
}

在每一次的迭代之前,R 語言都會去檢查小括號 () 中的某種條件是否成立,判斷結果為邏輯值 TRUE 就會執行每次迭代要執行的程式;一但條件不成立,判斷結果為邏輯值 FALSE 就會離開迴圈。因此如果我們想將內建向量 month.name 分別輸出,寫作成 while 迴圈的話,可以寫成這樣:

i <- 1
while (i < 13){
   print(month.name[i])
   i <- i + 1
}
## [1] "January"
## [1] "February"
## [1] "March"
## [1] "April"
## [1] "May"
## [1] "June"
## [1] "July"
## [1] "August"
## [1] "September"
## [1] "October"
## [1] "November"
## [1] "December"

很重要的一行是 i <- i + 1,假如忘記寫這一行程式,我們的 while 迴圈會無限次數地一直輸出 “January”,原因是小括號 () 中條件(1 < 13)永遠都成立,所以不斷地執行 print(month.name[1])

12.1 兩種迴圈的運用時機

那麼在實際撰寫 R 語言程式的時候,我們何時應該運用 for 迴圈、何時應該運用 while 迴圈呢?一個簡單的判斷是:假如我們明確知道程式需要執行幾次(迭代次數),比如說我們知道 month.name 這個向量的長度為 12,就可以採用 for 迴圈或 while 迴圈,端看個人偏好;而在不知道迭代次數的情形下,我們就只能採用 while 迴圈了。

這個說法還是略嫌抽象,舉一個例子說明會比較好理解。假如我們現在投擲一枚公正的銅板,想知道總共需要投擲幾次才會出現三個正面,這就是一個不知道迭代次數的問題。運氣好一點也許投擲三次,三次都是正面;運氣差一點的也許要投擲十幾次才湊得齊三次正面。我們寫了一段簡單的程式來模擬這個過程,其中 sample() 就是從向量中隨機抽樣的函數,size 參數可以指定隨機抽樣的個數:

flip_results <- c() # 建立一個空的向量來放置每一次投擲的結果
coin <- c(TRUE, FALSE) # TRUE 代表正面,FALSE 代表反面
n_flips <- 1 # 從第一次投擲開始記錄

while (sum(flip_results) < 3){
    flip_results[n_flips] <- sample(coin, size = 1) # 將每次投擲結果記錄起來
    n_flips <- n_flips + 1 # 準備記錄下一次的投擲結果
}
flip_results # 印出每次投擲的紀錄
## [1]  TRUE  TRUE FALSE  TRUE
length(flip_results) # 總共投擲了幾次
## [1] 4

您可以試著自行執行幾輪,看看每一輪投擲次數的差異。