【Ruby 學習筆記 — 06】流程控制:迴圈(loops)

寫在前頭

Kimika@小鳥
小鳥的隨筆生活
4 min readJan 16, 2019

--

這個學習筆記系列作為我自己學習 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
end
print(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 了。

--

--