switch 敘述 讓你可以把一個值與多個可能的相符值做比較。相較於使用多個 else-if 敘述,它能讓你寫出更精簡的程式碼。switch 敘述以 switch 關鍵字開頭,後面接著要比較的值。接著你可以用 case 關鍵字定義各種情況,後面接著要比對的值。當沒有任何情況相符時,會用 default 關鍵字定義預設情況。和 else-if 敘述一樣,switch 敘述只會執行第一個相符情況所對應的程式區塊。
switch value {
case 1:
print("One")
case 2:
print("Two")
default:
print("Other")
}
來看看下面這個例子:
if str == "apple" {
print("Let's bake an apple crumble")
} else if str == "lemon" {
print("Let's bake a lemon meringue pie!")
} else if str == "peach" {
print("Let's bake a peach pie!")
} else {
print("Let's buy ice cream.")
}
也可以改寫成:
switch str {
case "apple":
print("Let's bake an apple crumble")
case "lemon":
print("Let's bake a lemon meringue pie!")
case "peach":
print("Let's bake a peach pie!")
default:
print("Let's buy ice cream.")
}
while 迴圈 是一種控制流程敘述,讓程式碼在特定條件為真時持續執行。Swift 提供兩種 while 迴圈:while 迴圈和 repeat-while 迴圈。while 迴圈的條件會在迴圈主體執行前先求值;如果條件為假,迴圈主體就完全不會執行。Swift 裡的 while 迴圈結構如下:
while <#condition#> {
<#code#>
}
這裡的迴圈會在 count 大於 0 時持續執行,因此會依序印出數字 2、1 和 "Liftoff!"。
var count = 2
while count > 0 {
print("\(count)…")
count -= 1
}
print("Liftoff!")
// prints:
// 2…
// 1…
// Liftoff!
repeat-while 迴圈 和 while 迴圈類似,但條件是在迴圈主體執行後才求值。這代表迴圈主體至少會執行一次,即使條件為假也一樣。Swift 裡的 repeat-while 迴圈結構如下:
repeat {
<#code#>
} while <#condition#>
這裡的迴圈只會執行一次,因為條件為假。由於它是 repeat-while 迴圈,迴圈主體會在條件求值前先執行一次。
var count = 2
repeat {
print("\(count)…")
} while count < 0
print("Liftoff!")
Swift 有一組敘述可以用來改變迴圈正常的控制流程。這些敘述稱為控制轉移敘述。你已經看過 return;這個概念會介紹其他的,包括 continue、break 和標籤。這個概念不會涵蓋 fallthrough,但你可以在 Swift 書籍 中讀到相關內容。
有時候需要提早跳到迴圈的下一次疊代,而不完成目前這次疊代中其餘的敘述。這時可以使用 continue 關鍵字。執行 continue 時,迴圈會跳到下一次檢查,看看是否能執行下一次疊代,也就是 while 和 repeat-while 迴圈中的 while,或是 for-in 迴圈中檢查序列裡是否還有下一個元素。
count = 1
while count < 6 {
count += 1
if count == 4 { continue }
print(count)
}
// prints:
// 2
// 3
// 5
break 用來提早離開迴圈。執行 break 時,迴圈會立刻結束,程式會繼續執行迴圈後面的第一個敘述。
for fruit in ["banana", "grapes", "apple", "strawberry", "kiwi", "lemon"] {
if !fruit.count.isMultiple(of: 2) { break }
print(fruit)
}
// prints:
// banana
// grapes
當迴圈形成巢狀時,有時會想用 break 或 continue 來離開或重新開始外層迴圈。這些外層迴圈包住使用 break 或 continue 的那個迴圈。在這種情況下,可以用標籤指定要離開或重新開始的迴圈。只要在開始迴圈的 while、repeat 或 for 前面放上名稱加冒號,就能為迴圈加上標籤。
想看看這樣使用標籤的效果,請看下面這個迴圈。
outerLoop: for fruit in ["banana", "grapes", "apple", "strawberry", "kiwi", "lemon"] {
print("\n--- \(fruit) ---")
for letter in fruit {
guard letter != "n" else { break outerLoop }
print(letter)
}
}
// prints:
// --- banana ---
// b
// a
你是一位專業的調酒師,負責為夜晚外出放鬆的客人調製美味飲料。但你想到,只要寫一點程式碼來協助工作,就能讓日子輕鬆一些。
不同的飲料需要的準備時間不同:
"beer"、"soda"和"water"各需要 0.5 分鐘。"shot"需要 1.0 分鐘,"mixed drink"需要 1.5 分鐘,"fancy drink"需要 2.5 分鐘,"frozen drink"需要 3.0 分鐘。實作函式timeToPrepare(drinks:),它接受引數drinks,該引數是一個字串陣列,代表需要準備的飲料。
這個函式應回傳準備陣列中所有飲料所需的總時間。
timeToPrepare(drinks: ["beer", "frozen drink", "shot"])
// returns 4.5
開始值班時,你要做的第一件事之一,就是確保裝萊姆角的小盒子為接下來的一班補滿。 萊姆有不同的大小,能切出的萊姆角數量也不同:一顆 "small" 萊姆可以切出 6 個萊姆角,一顆 "medium" 萊姆可以切出 8 個,一顆 "large" 萊姆則可以切出 10 個。
只要你還需要更多萊姆角,而且還有萊姆可以切,就從陣列中取出第一顆萊姆,並從你需要的數量中扣掉它對應的萊姆角數量。 持續這個過程,直到你不再需要任何萊姆角,或是萊姆用完為止。
實作函式makeWedges(needed:limes:),它接受引數needed,代表你需要切出的萊姆角數量,以及limes,代表一個字串陣列,內含你可以切的萊姆大小。
這個函式應回傳你總共切了幾顆萊姆。
makeWedges(needed: 25, limes: ["small", "small", "large", "medium", "small"])
// returns 4
恭喜!漫長的工作日快要結束了,你很快就能回家開發你的新應用程式。 但在你把訂單交接給下一班、離開之前,還有一連串的飲料訂單要做。
只要值班時間還有剩,你就要製作陣列中的第一筆訂單,然後把該筆訂單從陣列中移除。
接著,你可以依照函式timeToPrepare(drinks:)算出準備那筆訂單所花費的時間,並從剩餘的值班時間中扣掉。
實作函式finishShift(minutesLeft:remainingOrders:),它接受你值班剩餘的分鐘數(保證大於 0),以及一個非空的飲料訂單陣列。
這個函式應回傳在你值班結束前還來不及處理的訂單陣列。
finishShift(minutesLeft: 5, remainingOrders: [["beer", "frozen drink", "shot"], ["fancy drink", "soda"], ["beer", "beer", "water"], ["mixed drink", "frozen drink"]])
// returns [["beer", "beer", "water"], ["mixed drink", "frozen drink"]]
為了確保啤酒和汽水保持新鮮,你需要追蹤它們的訂單以及下單的時間。
實作函式orderTracker(orders: [(drink: String, time: String)]) -> (beer: (first: String, last: String, total: Int)?, soda: (first: String, last: String, total: Int)?),它在給定一份訂單與時間的清單時,回傳一對選擇性的元組,內含啤酒與汽水第一筆及最後一筆訂單的時間,以及各自的訂單總數;若沒有那些飲料的訂單,則值為nil。你不需要追蹤其他任何飲料。
實作函式orderTracker(orders:),它接受一個元組陣列,其中每個元組包含所點的飲料以及下單的時間。
這個函式應回傳一個元組,內含啤酒第一筆與最後一筆的下單時間、啤酒訂單總數、汽水第一筆與最後一筆的下單時間,以及汽水訂單總數。
其格式應為:(beer: (first: String, last: String, total: Int)?, soda: (first: String, last: String, total: Int)?)。
let orders = [
(drink: "beer", time: "10:01"), (drink: "frozen drink", time: "10:02"),
(drink: "shot", time: "10:05"), (drink: "fancy drink", time: "10:06"),
(drink: "soda", time: "10:09"), (drink: "beer", time: "10:15"), (drink: "beer", time: "10:22"),
(drink: "water", time: "10:26"), (drink: "mixed drink", time: "10:28"),
(drink: "frozen drink", time: "10:33"),
]
orderTracker(orders: orders)
// returns (beer: (first "10:01", last "10:22", total 3), soda: (first "10:09", last "10:09", total 1))