7.3 條件語句

7.3 條件語句

我們總會遇到這樣的需求:

如果下雨就打雨傘,如果出太陽就打遮陽傘,其他情況不打傘

或者

成績在90分以上的學生獲得優秀獎,在80分以上的獲得出色獎,在60以上的獲得努力獎,其他的被批評。

這就是條件,事情的發生很多都是有條件的。Swift 提供了兩種條件語句,ifswitchif適合簡單的情況,比如:

男生請左轉,女生請右轉

switch 適合相對復雜的情況,比如上面根據分數評等級的例子。

If

if會執行條件語句,如果是true則執行一段代碼,否則跳過。如

var temperatureInCelsius = 16
if temperatureInCelsius <= 20 {
  println("It's a little cold. Consider wearing a scarf.")
}

這個例子判斷了當前的天氣,如果低于5攝氏度,就輸出這句溫馨的關懷。
當然可以更復雜一些:

var temperaturInCelsius = 24
if temperaturInCelsius <= 20 {
  println("It's a little cold. Consider wearing a scarf.")
} else {
  println("It's not that cold. Wear a t-shirt.")
}

這段代碼多了一個else分句,該分句就是我們平時說的,否則。這段代碼首先判斷了當前的溫度,如果低于20提示你要帶一條圍巾,否則穿一件t-shirt。
還可以更復雜一些:

var temperaturInCelsius = 32
if temperaturInCelsius <= 20 {
  println("It's a little cold. Consider wearing a scarf.")
} else if temperaturInCelsius >= 30 {
  println("It's really warm. Don't forget to wear sunscreen.")
} else {
  println("It's not that cold. Wear a t-shirt.")
}

可見我們可以連續使用ifelse ifelse,表達一個完整的意思。如果上面的一個ifelse if條件語句true那么就會進入該ifelse if的代碼區域執行代碼,之后跳出整個if,而不會繼續執行后面的 else if

如果男生就向左轉,否則向右轉:

var gender = "Male"
if gender == "Male" {
  println("Turn left")
} else {
  println("Turn right")
}

如果下雨就打雨傘,如果出太陽就打遮陽傘,其他情況不打傘

var weather = "sunny"
if weather == "sunny" {
  println("Take a bumbersoll with you")
} else if weather == "rainy" {
  println("Take an umbrella with you")
}

成績在90分以上的學生獲得優秀獎,在80分以上的獲得出色獎,在60以上的獲得努力獎,其他的被批評。

var score = 100
if score >= 90 {
  println("Excellent")
  // 代碼執行完這句話,不會繼續執行下面的判斷,而是跳出整個if
} else if score >= 80 {
  println("Good")
} else if score >= 60 {
  println("OK)
} else {
  println("Work harder")
}

Switch

switch用于較復雜的情況。switch的標準格式如下:

switch VALUE_TO_TEST {
  case VALUE_1:
    ACTIONS_TO_VALUE_1
  case VALUE_2,
  VALUE_3:
    ACTIONS_TO_VALUE_2_OR_VALUE_3
  default:
    ACTIONS_IF_NOT_MATCHED
}

每個switch語句都是由多情況斷組成的,每個情況由關鍵字case開始,case后是進入這個情況的條件。除了由case開始的情況外,還有由default開始的,稱之為默認情況。每個情況都必須相應的代碼段,而不能為空。switch根據VALUE_TO_TEST的值,判斷該進入哪個情況執行該情況,執行相應的代碼。
每個switch語句都需要是完備的。就是說每一個VALUE_TO_TEST的可能值,都必須出現在一個情況中。如果由case引導的情況沒有成功匹配VALUE_TO_TEST的值,那么就會進入默認情況。如果由case引導的情況不是完備的,則必須包含默認情況。
下面的例子判斷了一個字母是否為元音:

let someCharacter: Character = "e"
switch someCaracter {
case "a", "e", "i", "o", "u":
  println("\(someCharacter) is a vowel")
case "b", "c", "d", "f", "g", "h", "j", "k", "l", "m", "n", "p", "q", "r", "s", "t", "v", "w", "x", "y", "z":
  println("\(someCharacter) is a consonant")
default:
  println("\(someCharacter) is not a vowel or a consonant")
}

不同情況間不會穿越

與 C 和 Objective-C 不同,Swift 的switch的情況不會穿越,除非顯式的指出我們需要穿越。
例如下面這段代碼,Swift 編譯器會報錯:

let anotherCharacter: Character = "a"
switch anotherCharacher {
case "a":
case "A":
  println("The letter A")
default:
  println("Not the letter A")
}

在 C 中,無論"a"或者"A"都會輸出"The letter A",并且還會繼續輸出"Not the letter A"; 但是在 Swift 中,編譯器會報錯。這種情況我們應該使用 Swift 提供的多值匹配:

let anotherCharacter: Character = "a"
switch anotherCharacher {
case "a", "A":
  println("The letter A")
default:
  println("Not the letter A")
}

后面章節會介紹關鍵字fallthrough,該關鍵字可以使Swift的情況穿越

范圍匹配

當我們判斷一個數字的范圍時,多值匹配變得力不從心。例如我們想根據銀河中的星星個數輸出一句文字描述其數字的范圍:

let count = 3_000_000_000_000
let countedThings = "stars in the Milky Way"
var naturalCount: String
switch count {
case 0:
    naturalCount = "no"
case 1...3:
    naturalCount = "a few"
case 4...9:
    naturalCount = "several"
case 10...99:
    naturalCount = "tens of"
case 100...999:
    naturalCount = "hundreds of"
case 1000...999_999:
    naturalCount = "thousands of"
default:
    naturalCount = "millions and millions of"
}
println("There are \(naturalCount) \(countedThings).")

元組匹配

Swift 的switch支持同時匹配多個值,使用元組將其組合起來,成為一個元組變量,傳入switch進行比較。比較兩個元組時,有時我們只想比較其中某個位置的值,此時我們可以用下劃線忽略不需要比較的位置。
這回我們用直角坐標系來舉個例子。我們在坐標系中繪制一個邊長為4的正方形,其四個定點分別在(2,2)、(2,-2)、(-2,-2)以及(-2,2)。然后我們判斷該坐標系中的一個點是處于原點、坐標軸上還是我們的方框內。

let somePoint = (1, 1)
switch somePoint {
case (0, 0):
    println("(0, 0) is at the origin")
case (_, 0):
    println("(\(somePoint.0), 0) is on the x-axis")
case (0, _):
    println("(0, \(somePoint.1)) is on the y-axis")
case (-2...2, -2...2):
    println("(\(somePoint.0), \(somePoint.1)) is inside the box")
default:
    println("(\(somePoint.0), \(somePoint.1)) is outside of the box")
}

somePoint同時滿足多個情況時,第一個滿足的情況會被執行,而其他的都會被跳過。

值綁定

switch情況的條件語句可以進行值綁定,可以將值綁定到一個作用域為該情況代碼段的常量或變量上。
還是用直角坐標系舉例:

let anotherPoint = (2, 0)
switch anotherPoint {
case (let x, 0):
    println("on the x-axis with an x value of \(x)")
case (0, let y):
    println("on the y-axis with a y value of \(y)")
case let (x, y):
    println("somewhere else at (\(x), \(y))")
}

switch語句判斷anotherPoint是否在坐標軸上,如果是輸出其非0的坐標。
該例中第一個情況綁定了anotherPoint的橫坐標,并將其縱坐標被限制為0,任何縱坐標為 0 的點都會進入這種情況,包含原點和其他 x 軸上的點。橫坐標被綁定在名為x的常量上;第二個情況綁定了縱坐標,并限制橫坐標為0,除了原點外,所有 y 軸上的點都被匹配到這個情況中;而其他的所有不在坐標軸上的點都進入了第三個情況,我們分別綁定了該點的橫縱坐標。
因為所有以case引導的情況已經可以完備的表達點在直角坐標系的全部情況,所以不需要default了。

Where

switch的情況,除了可以進行值匹配以外還可以通過where子句進行附加條件判斷。
我們還用直角坐標系舉例,我們想判斷一個點是否在直角坐標系的對角線上。

let yetAnotherPoint = (1, -1)
switch yetAnotherPoint {
case let (x, y) where x == y:
    println("(\(x), \(y)) is on the line x == y")
case let (x, y) where x == -y:
    println("(\(x), \(y)) is on the line x == -y")
case let (x, y):
    println("(\(x), \(y)) is just some arbitrary point")
}

三種情況都進行了值綁定,綁定后我們又進行了進一步條件判斷。第一個情況中,我們判斷該點的橫縱坐標是否相同,這樣的點在一三象限的角平分線上;第二個情況中,我們判斷改點的橫縱坐標是否相反,這樣的點在二四象限的角平分線上;其余的情況通過不帶where子句的值綁定匹配。

最后編輯于
?著作權歸作者所有,轉載或內容合作請聯系作者
平臺聲明:文章內容(如有圖片或視頻亦包括在內)由作者上傳并發布,文章內容僅代表作者本人觀點,簡書系信息發布平臺,僅提供信息存儲服務。

推薦閱讀更多精彩內容

  • Spring Cloud為開發人員提供了快速構建分布式系統中一些常見模式的工具(例如配置管理,服務發現,斷路器,智...
    卡卡羅2017閱讀 134,993評論 19 139
  • SwiftDay011.MySwiftimport UIKitprintln("Hello Swift!")var...
    smile麗語閱讀 3,865評論 0 6
  • 53.計算字符 在字符串中獲取字符值的數量, 可以使用字符串字符屬性中的計數屬性: let unusualMena...
    無灃閱讀 1,140評論 0 4
  • LDA(Latent Dirichlet Allocation)是一種文檔主題生成模型,也稱為一個三層貝葉斯概率模...
    chaaffff閱讀 1,935評論 0 2
  • 模式定義 定義一系列算法,將它們一個個封裝起來,并且使他們之間可以相互替換。本模式使得算法可以獨立于使用它的客戶而...
    FX_SKY閱讀 254評論 0 0