【Ruby 學習筆記 — 06】流程控制:迴圈(loops)
這個學習筆記系列作為我自己學習 Ruby 過程中筆記整理,Main purpose 是提供自己將來隨時 refer,而不是一個教程系列,加上本身有其他語言經驗因此很多概念和名詞不會多作解釋,因此不適合沒有任何程式基礎的讀者。Happy Coding !
迴圈(loops)
迴圈是程式設計中非常重要的部份,Ruby 中迴圈有許多作法。
1. while 迴圈
while 迴圈是最基本的一種,幾乎每種程式語言都有實作,while 迴圈利用條件式決定執行與否,code block 中要能夠讓迴圈結束,否則會形成無窮迴圈。
一樣需要加上 end 關上 code block
while 條件
# do something
end
以下是一個實例
count = 0while count < 3
print count
count+=1
end# output : 012
until
迴圈的概念有點像 if,因此就如 if 相對有著 unless,while 也相對有著until
count = 0while count >= 3
print count
count+=1
end# output : 012
break, next
有時候我們不設定條件,或是想要在 code block 中主動控制迴圈:
break 可以直接跳出整個迴圈
next 則是跳到下一次迭代,在許多程式語言裡叫做 continue
上面的例子可以寫成這個樣子:
count = 0while true
if count >= 3
break
end print count
count+=1
end# output : 012
loop
有時候我們不想設定條件,會寫成 while true 的形式,Ruby 提供了 loop 這個keyword,不過要再加上 do。
count = 0loop do
if count >= 3
break
endprint(count)
count+=1
end# output : 012
2. for-in 迴圈
for 迴圈在很多程式語言大概幾乎是最常使用的迴圈,不過 ruby 中並不像很多語言如 java 的 for(int i=0;i<5;i++) 這種迴圈,只有 for-in 迴圈,通常用來迭代陣列中的元素。
如以下示例印出陣列中所有元素
nums = [1,2,3,4,5]for num in nums
print num
end# output : 12345
3. 迭代 (prefered)
相較於 for-in 迴圈,許多文件、教學們都建議使用迭代器。
對可迭代對象如陣列、許多方法都會回傳的 enumerable 對象進行迭代。
# times
用 times 對知道次數的迴圈特別有用,可讀性也非常高,接近英文文法
3.times do
print('-')
end# output : ---
# each
each 應該是最常使用的一種方法,有點類似有些程式語言會有的 forEach 方法,對對象中所有元素迭代。
arr = ['hello', 'everyone', 'my', 'name', 'is', 'hank']arr.each do |item|
print item + ' '
end# output : hello everyone my name is hank
do 後面在兩個直線中間的變數,是 code block 中的區域變數,或者我都想成 javascript 中 forEach callback 的參數,迭代陣列的話就是每個元素,當然每種方法有每種方法會提供的變數,有些也會有兩個變數。
code block in one line
我們 code block 中只有一行程式碼時,可以寫成一行
nums = [1,2,3,4,5]nums.each do |num| print num; end# output : 12345
do..end 寫成一行時要加上分號( ; )
不過風格指南告訴我們
一行時應該使用 大括號 {}
多行時應該使用 do..end
nums = [1,2,3,4,5]nums.each { |num| print num }# output : 12345
大括號 { } 與 do..end 的差異
除了習慣與風格統一的問題
大括號和 do..end 還有一個差別
如以下例子:
nums = [1,2,3]p nums.map { |num| num + 1 } # output : [2, 3, 4]############################################p nums.map do |num| num + 1; end # output : #<Enumerator: [1, 2, 3]:map>
可見大括號和 do..end 還有優先度的差異
使用大括號時,程式碼是跑完了迭代,才讓 p 印出
使用 do..end 卻是印出了 nums.map 回傳的物件,表示還沒有執行block就已經先執行 p 了。