Added information about comparing tuples.
This commit is contained in:
@ -11,30 +11,33 @@
|
||||
> 2.1
|
||||
> 校对:[shanks](http://codebuild.me)
|
||||
|
||||
> 2.2
|
||||
> 翻译+校对:[Cee](https://github.com/Cee)
|
||||
|
||||
本页包含内容:
|
||||
|
||||
- [术语](#terminology)
|
||||
- [赋值运算符](#assignment_operator)
|
||||
- [算术运算符](#arithmetic_operators)
|
||||
- [组合赋值运算符(Compound Assignment Operators)](#compound_assignment_operators)
|
||||
- [组合赋值运算符](#compound_assignment_operators)
|
||||
- [比较运算符](#comparison_operators)
|
||||
- [三目运算符(Ternary Conditional Operator)](#ternary_conditional_operator)
|
||||
- [三目运算符](#ternary_conditional_operator)
|
||||
- [空合运算符](#nil_coalescing_operator)
|
||||
- [区间运算符](#range_operators)
|
||||
- [逻辑运算符](#logical_operators)
|
||||
|
||||
运算符是检查、改变、合并值的特殊符号或短语。例如,加号`+`将两个数相加(如`let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符`&&`(如`if enteredDoorCode && passedRetinaScan`),或让 i 值加1的便捷自增运算符`++i`等。
|
||||
运算符是检查、改变、合并值的特殊符号或短语。例如,加号(`+`)将两个数相加(如 `let i = 1 + 2`)。更复杂的运算例子包括逻辑与运算符 `&&`(如 `if enteredDoorCode && passedRetinaScan`),或让 i 值加 1 的便捷自增运算符 `++i` 等。
|
||||
|
||||
Swift 支持大部分标准 C 语言的运算符,且改进许多特性来减少常规编码错误。如:赋值符(`=`)不返回值,以防止把想要判断相等运算符(`==`)的地方写成赋值符导致的错误。算术运算符(`+`,`-`,`*`,`/`,`%`等)会检测并不允许值溢出,以此来避免保存变量时由于变量大于或小于其类型所能承载的范围时导致的异常结果。当然允许你使用 Swift 的溢出运算符来实现溢出。详情参见[溢出运算符](../chapter2/25_Advanced_Operators.html#overflow_operators)。
|
||||
|
||||
区别于 C 语言,在 Swift 中你可以对浮点数进行取余运算(`%`),Swift 还提供了 C 语言没有的表达两数之间的值的区间运算符(`a..<b` 和 `a...b`),这方便我们表达一个区间内的数值。
|
||||
|
||||
本章节只描述了 Swift 中的基本运算符,[高级运算符](../chapter2/25_Advanced_Operators.html)包含了高级运算符,及如何自定义运算符,及如何进行自定义类型的运算符重载。
|
||||
本章节只描述了 Swift 中的基本运算符,[高级运算符](../chapter2/25_Advanced_Operators.html)这章会包含 Swift 中的高级运算符,及如何自定义运算符,及如何进行自定义类型的运算符重载。
|
||||
|
||||
<a name="terminology"></a>
|
||||
## 术语
|
||||
|
||||
运算符有一元、二元和三元运算符。
|
||||
运算符分为一元、二元和三元运算符。
|
||||
|
||||
- 一元运算符对单一操作对象操作(如 `-a`)。一元运算符分前置运算符和后置运算符,前置运算符需紧跟在操作对象之前(如 `!b`),后置运算符需紧跟在操作对象之后(如 `i++`)。
|
||||
- 二元运算符操作两个操作对象(如 `2 + 3`),是中置的,因为它们出现在两个操作对象之间。
|
||||
@ -58,7 +61,7 @@ a = b
|
||||
|
||||
```swift
|
||||
let (x, y) = (1, 2)
|
||||
// 现在 x 等于 1, y 等于 2
|
||||
// 现在 x 等于 1,y 等于 2
|
||||
```
|
||||
|
||||
与 C 语言和 Objective-C 不同,Swift 的赋值操作并不返回任何值。所以以下代码是错误的:
|
||||
@ -69,7 +72,7 @@ if x = y {
|
||||
}
|
||||
```
|
||||
|
||||
这个特性使你无法把(`==`)错写成(`=`),由于`if x = y`是错误代码,Swift帮你避免此类错误的的发生。
|
||||
这个特性使你无法把(`==`)错写成(`=`),由于 `if x = y` 是错误代码,Swift 能帮你避免此类错误发生。
|
||||
|
||||
<a name="arithmetic_operators"></a>
|
||||
## 算术运算符
|
||||
@ -101,13 +104,13 @@ Swift 中所有数值类型都支持了基本的四则算术运算:
|
||||
求余运算(`a % b`)是计算 `b` 的多少倍刚刚好可以容入`a`,返回多出来的那部分(余数)。
|
||||
|
||||
> 注意:
|
||||
求余运算(`%`)在其他语言也叫取模运算。然而严格说来,我们看该运算符对负数的操作结果,"求余"比"取模"更合适些。
|
||||
求余运算(`%`)在其他语言也叫取模运算。然而严格说来,我们看该运算符对负数的操作结果,「求余」比「取模」更合适些。
|
||||
|
||||
我们来谈谈取余是怎么回事,计算 `9 % 4`,你先计算出 `4` 的多少倍会刚好可以容入 `9` 中:
|
||||
|
||||

|
||||
|
||||
2倍,非常好,那余数是1(用橙色标出)
|
||||
你可以在 `9` 中放入两个 `4`,那余数是 1(用橙色标出)。
|
||||
|
||||
在 Swift 中可以表达为:
|
||||
|
||||
@ -147,7 +150,7 @@ Swift 中所有数值类型都支持了基本的四则算术运算:
|
||||
8 % 2.5 // 等于 0.5
|
||||
```
|
||||
|
||||
这个例子中,`8`除于`2.5`等于`3`余`0.5`,所以结果是一个`Double`值`0.5`。
|
||||
这个例子中,`8` 除以 `2.5` 等于 `3` 余 `0.5`,所以结果是一个 `Double` 型的值为 `0.5`。
|
||||
|
||||

|
||||
|
||||
@ -162,9 +165,9 @@ var i = 0
|
||||
|
||||
每调用一次 `++i`,`i` 的值就会加 1。实际上,`++i` 是 `i = i + 1` 的简写,而 `--i` 是 `i = i - 1` 的简写。
|
||||
|
||||
`++`和`--`既可以用作前置运算又可以用作后置运算。`++i`,`i++`,`--i`和`i--`都是有效的写法。
|
||||
`++` 和 `--` 既可以用作前置运算又可以用作后置运算。`++i`、`i++` 都是有效的自增的写法;相类似对应自减的写法则是 `--i` 和 `i--`。
|
||||
|
||||
我们需要注意的是这些运算符即可修改了`i`的值也可以返回`i`的值。如果你只想修改`i`的值,那你就可以忽略这个返回值。但如果你想使用返回值,你就需要留意前置和后置操作的返回值是不同的,她们遵循以下原则:
|
||||
我们需要注意的是这些运算符即可修改了 `i` 的值也可以返回 `i` 的值。如果你只想修改 `i` 的值,那你就可以忽略这个返回值。但如果你想使用返回值,你就需要留意前置和后置操作的返回值是不同的,它们遵循以下原则:
|
||||
|
||||
- 当 `++` 前置的时候,先自増再返回。
|
||||
- 当 `++` 后置的时候,先返回再自增。
|
||||
@ -209,13 +212,14 @@ let alsoMinusSix = +minusSix // alsoMinusSix 等于 -6
|
||||
|
||||
|
||||
<a name="compound_assignment_operators"></a>
|
||||
## 组合赋值运算符(Compound Assignment Operators)
|
||||
## 组合赋值运算符
|
||||
|
||||
如同 C 语言,Swift 也提供把其他运算符和赋值运算(`=`)组合的组合赋值运算符,组合加运算(`+=`)是其中一个例子:
|
||||
|
||||
```swift
|
||||
var a = 1
|
||||
a += 2 // a 现在是 3
|
||||
a += 2
|
||||
// a 现在是 3
|
||||
```
|
||||
|
||||
表达式 `a += 2` 是 `a = a + 2` 的简写,一个组合加运算就是把加法运算和赋值运算组合成进一个运算符里,同时完成两个运算任务。
|
||||
@ -226,7 +230,7 @@ a += 2 // a 现在是 3
|
||||
在[表达式](../chapter3/04_Expressions.html)章节里有复合运算符的完整列表。
|
||||
|
||||
<a name="comparison_operators"></a>
|
||||
## 比较运算符
|
||||
## 比较运算符(Comparison Operators)
|
||||
|
||||
所有标准 C 语言中的比较运算都可以在 Swift 中使用:
|
||||
|
||||
@ -238,7 +242,7 @@ a += 2 // a 现在是 3
|
||||
- 小于等于(`a <= b`)
|
||||
|
||||
> 注意:
|
||||
Swift 也提供恒等`===`和不恒等`!==`这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](../chapter2/09_Classes_and_Structures.html)。
|
||||
Swift 也提供恒等(`===`)和不恒等(`!==`)这两个比较符来判断两个对象是否引用同一个对象实例。更多细节在[类与结构](../chapter2/09_Classes_and_Structures.html)。
|
||||
|
||||
每个比较运算都返回了一个标识表达式是否成立的布尔值:
|
||||
|
||||
@ -265,10 +269,23 @@ if name == "world" {
|
||||
|
||||
关于 `if` 语句,请看[控制流](../chapter2/05_Control_Flow.html)。
|
||||
|
||||
<a name="ternary_conditional_operator"></a>
|
||||
## 三目运算符(Ternary Conditional Operator)
|
||||
当元组中的值可以比较时,你也可以使用这些运算符来比较它们的大小。例如,因为 `Int` 和 `String` 类型的值可以比较,所以类型为 `(Int, String)` 的元组也可以被比较。相反,`Bool` 不能被比较,也意味着存有布尔类型的元组不能被比较。
|
||||
|
||||
三目运算符的特殊在于它是有三个操作数的运算符,它的原型是 `问题 ? 答案1 : 答案2`。它简洁地表达根据`问题`成立与否作出二选一的操作。如果`问题`成立,返回`答案1`的结果; 如果不成立,返回`答案2`的结果。
|
||||
比较元组大小会按照从左到右、逐值比较的方式,直到发现有两个值不等时停止。如果所有的值都相等,那么这一对元组我们就称它们是相等的。例如:
|
||||
|
||||
```swift
|
||||
(1, "zebra") < (2, "apple") // true,因为 1 小于 2
|
||||
(3, "apple") < (3, "bird") // true,因为 3 等于 3,但是 apple 小于 bird
|
||||
(4, "dog") == (4, "dog") // true,因为 4 等于 4,dog 等于 dog
|
||||
```
|
||||
|
||||
> 注意:
|
||||
Swift 标准库只能比较七个以内元素的元组比较函数。如果你的元组元素超过七个时,你需要自己实现比较运算符。
|
||||
|
||||
<a name="ternary_conditional_operator"></a>
|
||||
## 三目运算符(Ternary Conditional Operator)
|
||||
|
||||
三目运算符的特殊在于它是有三个操作数的运算符,它的形式是 `问题 ? 答案 1 : 答案 2`。它简洁地表达根据 `问题`成立与否作出二选一的操作。如果 `问题` 成立,返回 `答案 1` 的结果;反之返回 `答案 2` 的结果。
|
||||
|
||||
三目运算符是以下代码的缩写形式:
|
||||
|
||||
@ -308,23 +325,20 @@ if hasHeader {
|
||||
三目运算提供有效率且便捷的方式来表达二选一的选择。需要注意的事,过度使用三目运算符会使简洁的代码变的难懂。我们应避免在一个组合语句中使用多个三目运算符。
|
||||
|
||||
<a name="nil_coalescing_operator"></a>
|
||||
## 空合运算符(Nil Coalescing Operator)
|
||||
## 空合运算符(Nil Coalescing Operator)
|
||||
|
||||
空合运算符(`a ?? b`)将对可选类型`a`进行空判断,如果`a`包含一个值就进行解封,否则就返回一个默认值`b`.这个运算符有两个条件:
|
||||
空合运算符(`a ?? b`)将对可选类型 `a` 进行空判断,如果 `a` 包含一个值就进行解封,否则就返回一个默认值 `b`。表达式 `a` 必须是 Optional 类型。默认值 `b` 的类型必须要和 `a` 存储值的类型保持一致。
|
||||
|
||||
- 表达式`a`必须是Optional类型
|
||||
- 默认值`b`的类型必须要和`a`存储值的类型保持一致
|
||||
|
||||
空合运算符是对以下代码的简短表达方法
|
||||
空合运算符是对以下代码的简短表达方法:
|
||||
|
||||
```swift
|
||||
a != nil ? a! : b
|
||||
```
|
||||
|
||||
上述代码使用了三目运算符。当可选类型`a`的值不为空时,进行强制解封(`a!`)访问`a`中值,反之当`a`中值为空时,返回默认值b。无疑空合运算符(`??`)提供了一种更为优雅的方式去封装条件判断和解封两种行为,显得简洁以及更具可读性。
|
||||
上述代码使用了三目运算符。当可选类型 `a` 的值不为空时,进行强制解封(`a!`),访问 `a` 中的值;反之返回默认值 `b`。无疑空合运算符(`??`)提供了一种更为优雅的方式去封装条件判断和解封两种行为,显得简洁以及更具可读性。
|
||||
|
||||
> 注意:
|
||||
如果`a`为非空值(`non-nil`),那么值`b`将不会被估值。这也就是所谓的短路求值。
|
||||
如果 `a` 为非空值(`non-nil`),那么值 `b` 将不会被计算。这也就是所谓的短路求值。
|
||||
|
||||
下文例子采用空合运算符,实现了在默认颜色名和可选自定义颜色名之间抉择:
|
||||
|
||||
@ -336,10 +350,10 @@ var colorNameToUse = userDefinedColorName ?? defaultColorName
|
||||
// userDefinedColorName 的值为空,所以 colorNameToUse 的值为 "red"
|
||||
```
|
||||
|
||||
`userDefinedColorName`变量被定义为一个可选`String`类型,默认值为`nil`。由于`userDefinedColorName`是一个可选类型,我们可以使用空合运算符去判断其值。在上一个例子中,通过空合运算符为一个名为`colorNameToUse`的变量赋予一个字符串类型初始值。
|
||||
`userDefinedColorName` 变量被定义为一个可选的 `String` 类型,默认值为 `nil`。由于 `userDefinedColorName` 是一个可选类型,我们可以使用空合运算符去判断其值。在上一个例子中,通过空合运算符为一个名为 `colorNameToUse` 的变量赋予一个字符串类型初始值。
|
||||
由于 `userDefinedColorName` 值为空,因此表达式 `userDefinedColorName ?? defaultColorName` 返回 `defaultColorName` 的值,即 `red`。
|
||||
|
||||
另一种情况,分配一个非空值(`non-nil`)给`userDefinedColorName`,再次执行空合运算,运算结果为封包在`userDefaultColorName`中的值,而非默认值。
|
||||
另一种情况,分配一个非空值(`non-nil`)给 `userDefinedColorName`,再次执行空合运算,运算结果为封包在 `userDefaultColorName` 中的值,而非默认值。
|
||||
|
||||
```swift
|
||||
userDefinedColorName = "green"
|
||||
@ -348,12 +362,12 @@ colorNameToUse = userDefinedColorName ?? defaultColorName
|
||||
```
|
||||
|
||||
<a name="range_operators"></a>
|
||||
## 区间运算符
|
||||
## 区间运算符(Range Operators)
|
||||
|
||||
Swift 提供了两个方便表达一个区间的值的运算符。
|
||||
|
||||
### 闭区间运算符
|
||||
闭区间运算符(`a...b`)定义一个包含从`a`到`b`(包括`a`和`b`)的所有值的区间,`b`必须大于等于`a`。
|
||||
闭区间运算符(`a...b`)定义一个包含从 `a` 到 `b`(包括 `a` 和 `b`)的所有值的区间。`a` 的值不能超过 `b`。
|
||||
|
||||
闭区间运算符在迭代一个区间的所有值时是非常有用的,如在 `for-in` 循环中:
|
||||
|
||||
@ -375,7 +389,7 @@ for index in 1...5 {
|
||||
半开区间(`a..<b`)定义一个从 `a` 到 `b` 但不包括 `b` 的区间。
|
||||
之所以称为半开区间,是因为该区间包含第一个值而不包括最后的值。
|
||||
|
||||
半开区间的实用性在于当你使用一个从0开始的列表(如数组)时,非常方便地从0数到列表的长度。
|
||||
半开区间的实用性在于当你使用一个从 0 开始的列表(如数组)时,非常方便地从0数到列表的长度。
|
||||
|
||||
```swift
|
||||
let names = ["Anna", "Alex", "Brian", "Jack"]
|
||||
@ -389,10 +403,10 @@ for i in 0..<count {
|
||||
// 第 4 个人叫 Jack
|
||||
```
|
||||
|
||||
数组有4个元素,但`0..<count`只数到3(最后一个元素的下标),因为它是半开区间。关于数组,请查阅[数组](../chapter2/04_Collection_Types.html#arrays)。
|
||||
数组有 4 个元素,但 `0..<count` 只数到3(最后一个元素的下标),因为它是半开区间。关于数组,请查阅[数组](../chapter2/04_Collection_Types.html#arrays)。
|
||||
|
||||
<a name="logical_operators"></a>
|
||||
## 逻辑运算
|
||||
## 逻辑运算(Logical Operators)
|
||||
|
||||
逻辑运算的操作对象是逻辑布尔值。Swift 支持基于 C 语言的三个标准逻辑运算。
|
||||
|
||||
@ -414,7 +428,7 @@ if !allowedEntry {
|
||||
// 输出 "ACCESS DENIED"
|
||||
```
|
||||
|
||||
`if !allowedEntry`语句可以读作“如果非 allowedEntry。”,接下一行代码只有在“非 allowedEntry”为`true`,即`allowEntry`为`false`时被执行。
|
||||
`if !allowedEntry` 语句可以读作「如果非 allowedEntry」,接下一行代码只有在「非 allowedEntry」为 `true`,即 `allowEntry` 为 `false` 时被执行。
|
||||
|
||||
在示例代码中,小心地选择布尔常量或变量有助于代码的可读性,并且避免使用双重逻辑非运算,或混乱的逻辑语句。
|
||||
|
||||
@ -422,9 +436,9 @@ if !allowedEntry {
|
||||
|
||||
逻辑与(`a && b`)表达了只有 `a` 和 `b` 的值都为 `true` 时,整个表达式的值才会是 `true`。
|
||||
|
||||
只要任意一个值为`false`,整个表达式的值就为`false`。事实上,如果第一个值为`false`,那么是不去计算第二个值的,因为它已经不可能影响整个表达式的结果了。这被称做“短路计算(short-circuit evaluation)”。
|
||||
只要任意一个值为 `false`,整个表达式的值就为 `false`。事实上,如果第一个值为 `false`,那么是不去计算第二个值的,因为它已经不可能影响整个表达式的结果了。这被称做「短路计算(short-circuit evaluation)」。
|
||||
|
||||
以下例子,只有两个`Bool`值都为`true`的时候才允许进入:
|
||||
以下例子,只有两个 `Bool` 值都为 `true` 的时候才允许进入 if:
|
||||
|
||||
```swift
|
||||
let enteredDoorCode = true
|
||||
@ -441,7 +455,7 @@ if enteredDoorCode && passedRetinaScan {
|
||||
|
||||
逻辑或(`a || b`)是一个由两个连续的 `|` 组成的中置运算符。它表示了两个逻辑表达式的其中一个为 `true`,整个表达式就为 `true`。
|
||||
|
||||
同逻辑与运算类似,逻辑或也是“短路计算”的,当左端的表达式为`true`时,将不计算右边的表达式了,因为它不可能改变整个表达式的值了。
|
||||
同逻辑与运算类似,逻辑或也是「短路计算」的,当左端的表达式为 `true` 时,将不计算右边的表达式了,因为它不可能改变整个表达式的值了。
|
||||
|
||||
以下示例代码中,第一个布尔值(`hasDoorKey`)为 `false`,但第二个值(`knowsOverridePassword`)为 `true`,所以整个表达是 `true`,于是允许进入:
|
||||
|
||||
|
||||
Reference in New Issue
Block a user