# Day 6 - Loops, summary, and checkpoint 3
## How to use a for loop to repeat work
- 電腦很適合做重複性高的工作,Swift允許做一個固定次數的重複動作,或是針對一個 `array` 、 `set` 或 `dictionary` 中的每一項各做一次同種動作
- ex: 針對 `array` 中的每一項各做一次同種動作
```
let platforms = ["iOS", "macOS", "tvOS", "watchOS"]
for os in platforms {
print("Swift works great on \(os)")
}
// Swift works great on iOS
Swift works great on macOS
Swift works great on tvOS
Swift works great on watchOS
```
- loop body
```
print("Swift works great on \(os)")
```
- loop iteration
```
for os in platforms {
print("Swift works great on \(os)")
}
```
- loop variable: `os`
- ex: 指定一個動作重複做幾次
```
for i in 1...12 {
print("5 x \(i) = \(5 * i)")
}
// 5 x 1 = 5
5 x 2 = 10
5 x 3 = 15
5 x 4 = 20
5 x 5 = 25
5 x 6 = 30
5 x 7 = 35
5 x 8 = 40
5 x 9 = 45
5 x 10 = 50
5 x 11 = 55
5 x 12 = 60
```
- loop variable的命名convention: `i` -> `j` -> `k`
- ex: 巢狀(nested)loop,在loop裡面再多幾層loop
```
for i in 1...3 {
print("The \(i) times table")
for j in 1...5 {
print(" \(j) * \(i) is \(j * i)")
}
print()
}
// The 1 times table
1 * 1 is 1
2 * 1 is 2
3 * 1 is 3
4 * 1 is 4
5 * 1 is 5
The 2 times table
1 * 2 is 2
2 * 2 is 4
3 * 2 is 6
4 * 2 is 8
5 * 2 is 10
The 3 times table
1 * 3 is 3
2 * 3 is 6
3 * 3 is 9
4 * 3 is 12
5 * 3 is 15
```
- 只想loop不含最後一個數字的情況: `..<`
```
for i in 1...5 {
print("Counting from 1 through 5: \(i)")
}
// Counting from 1 through 5: 1
Counting from 1 through 5: 2
Counting from 1 through 5: 3
Counting from 1 through 5: 4
Counting from 1 through 5: 5
for i in 1..<5 {
print("Counting from 1 up to 5: \(i)")
}
// Counting from 1 up to 5: 1
Counting from 1 up to 5: 2
Counting from 1 up to 5: 3
Counting from 1 up to 5: 4
```
- 有時候不需要用到loop variable,可以用 `_` 代替
```
var lyric = "Haters gonna"
for _ in 1...5 {
lyric += " hate"
}
print(lyric)
// Haters gonna hate hate hate hate hate
```
### Optional: Why does Swift use underscores with loops?
- Swift能檢查你是否在 loop 裡有用到 loop variable,如果沒有的話,會在你命名loop variable時報錯,請你改為 `_` ,這樣在看 code 的時候一眼就能看出這段 loop 沒有使用到該 variable
### Optional: Why does Swift have two range operators?
- 「範圍是否要包含指向的最後一個數字」在實務中是很常見的問題,因此Swift提供兩種範圍運算子:`...`(包含後者)及 `..<`(不包含後者)
- `...`: 1 through 5
- `..<`: 1 to 5
- 如果不確定最後的index,可以這樣: `print(names[1...])` 取得從index為1的值到 array 的最後一個值
## How to use a while loop to repeat work
- 給定一個條件,Swift的 `while` 會一直重複執行動作直到該條件不再符合
- `for` loop還是比 `while` loop 更常被使用
```
var countdown = 10
while countdown > 0 {
print("\(countdown)")
countdown -= 1
}
print("Blast off!")
// 10
9
8
7
6
5
4
3
2
1
Blast off!
```
- `while` 在不知道確切要執行幾次的情況下很好用
```
var roll = 0
while roll != 20 {
roll = Int.random(in: 1...20)
print("I rolled a \(roll)")
}
print("Critical hit!")
// I rolled a 19
I rolled a 7
I rolled a 19
I rolled a 13
I rolled a 13
I rolled a 16
I rolled a 16
I rolled a 20
Critical hit!
```
- `random(in: )` :在某範圍內隨機產生一個值
### Optional: When should you use a while loop?
- `for` loop 通常是用在有限的情況下,例如從數字1到10、或遍歷一個array中的items
- `while` loop 則是可以一直重複直到一個任意的條件變成false,例如使用者要求停止、伺服器要求停止、找到要找的答案、產生足夠的資料等條件
- 有時候就是無法預料某情況會需要loop幾次,所以需要用 `while` 來判斷
## How to skip loop items with break and continue
#### continue
- 在沒有指定 `continue` 的情況下,loop一旦遇到不符合條件的item就會終止
- 但某些情況下,我們希望loop跳過不符合條件的item,然後繼續跑完剩下的loop
```
let filenames = ["me.jpg", "work.txt", "Sophie.jpg"]
for filename in filenames {
if filename.hasSuffix(".jpg") == false {
continue
}
print("Found picture: \(filename)")
}
// Found picture: me.jpg
Found picture: Sophie.jpg
```
#### break
- 在某條件下 `break`,會立即終止loop,不論後面是否還有item
```
let number1 = 4
let number2 = 14
var multiples = [Int]()
for i in 1...100_000 {
if i.isMultiple(of: number1) && i.isMultiple(of: number2) {
multiples.append(i)
if multiples.count == 10 {
break
}
}
}
print(multiples)
// [28, 56, 84, 112, 140, 168, 196, 224, 252, 280]
```
### Optional: Why would you want to exit a loop?
- 某些情況下,不需要遍歷整個array或range就可以得到答案,這時使用 `break` 可以節省時間或運算,例如要計算玩家連續幾局沒有得到0分,當一遇到0分就 `break`
### Optional: Why does Swift have labeled statements?
- 在 nested loops 的情況下,如果需要在某條件發生時一次結束所有loop ,可以為最外層的 loop 取名,`break` 時直接指定該 loop 名即可
```
outerLoop: for option1 in options {
for option2 in options {
for option3 in options {
print("In loop")
let attempt = [option1, option2, option3]
if attempt == secretCombination {
print("The combination is \(attempt)!")
break outerLoop
}
}
}
}
```
### Optional: When to use break and when to use continue
- `continue` 代表的是跳過「目前執行的項目」; `break` 則是跳過「剩下的所有項目」
## Summary: Conditions and loops
- 我們用 `if` 、 `else` 、 `else if` 來檢查條件
- 可以用 或(`||`)、且(`&&`) 來結合不同條件
- `switch` 使用起來會比 `if` 、 `else if` 容易,而且Swift會檢驗它們是否覆蓋了所有可能情況
- 三元運算子讓我們檢驗「WTF」,`What?` ? `True` : `False`
- `for` loop 讓我們在 `array` 、 `set` 、 `dictionary` 或一定範圍內重複執行某動作
- `while` loop 重複執行某動作直到該條件不符合
- 用 `continue` 或 `break` 以不同方式跳過loop