Swift5.1 语言指南(五) 基本运算符

★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★
➤微信公众号:山青咏芝(shanqingyongzhi)
➤博客园地址:山青咏芝(https://www.cnblogs.com/strengthen/
➤GitHub地址:https://github.com/strengthen/LeetCode
➤原文地址:https://www.cnblogs.com/strengthen/p/9720408.html 
➤如果链接不是山青咏芝的博客园地址,则可能是爬取作者的文章。
➤原文已修改更新!强烈建议点击原文地址阅读!支持作者!支持原创!
★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★★

一个运营商是一个特殊的符号,或者你使用来检查,更改或合并值的短语。例如,加法运算符(+)添加两个数字,如,和逻辑AND运算符()组合两个布尔值,如。let 2&&if enteredDoorCode && passedRetinaScan

Swift支持大多数标准C运算符,并改进了几种消除常见编码错误的功能。赋值运算符(=)不返回值,以防止在等于operator(==)的意图时错误地使用它。算术运算符(+-*/%等等)检测和禁止值溢出,与变得比存储它们的类型的所允许的值的范围更大或更小数目的工作时避免意外的结果。您可以通过使用雨燕的溢出运营商选择在价值溢出行为,如在溢出运营商

Swift还提供了在C中找不到的范围运算符,例如a..<ba...b表示一系列值的快捷方式。

本章介绍Swift中的常用运算符。高级操作员涵盖了Swift的高级操作符,并描述了如何定义自己的自定义操作符并为您自己的自定义类型实现标准操作符。

术语

运算符是一元的,二元的或三元的:

  • 一元运算符在单个目标上运行(例如-a)。一元前缀运算符出现在它们的目标之前(例如!b),并且一元后缀运算符紧跟在它们的目标之后(例如c!)。
  • 二元运算符在两个目标(例如)上运行,并且是中缀,因为它们出现在两个目标之间。3
  • 三元运营商在三个目标上运营。与C一样,Swift只有一个三元运算符,即三元条件运算符()。c

运算符影响的值是操作数。在表达式中,符号是二元运算符,它的两个操作数是值和。2+12

分配操作员

赋值运算符()初始化或更新的价值与价值:bab

  1. let b = 10
  2. var a = 5
  3. a = b
  4. // a is now equal to 10

如果赋值的右侧是具有多个值的元组,则其元素可以一次分解为多个常量或变量:

  1. let (x, y) = (1, 2)
  2. // x is equal to 1, and y is equal to 2

与C和Objective-C中的赋值运算符不同,Swift中的赋值运算符本身不返回值。以下声明无效:

  1. if x = y {
  2. // This is not valid, because x = y does not return a value.
  3. }

此功能可防止在实际=使用等于operator(==)时意外使用赋值运算符()。通过使无效,Swift可以帮助您避免代码中的这类错误。if y

算术运算符

Swift支持所有数字类型的四个标准算术运算符

  • 加法(+
  • 减法(-
  • 乘法(*
  • 师(/
  1. 1 + 2 // equals 3
  2. 5 - 3 // equals 2
  3. 2 * 3 // equals 6
  4. 10.0 / 2.5 // equals 4.0

与C和Objective-C中的算术运算符不同,Swift算术运算符默认情况下不允许值溢出。您可以通过使用Swift的溢出运算符(例如)来选择值溢出行为。请参阅溢出运算符&+ b

String连接运算符也支持连接:

  1. "hello, " + "world" // equals "hello, world"

剩余运营商

余运算符()的作品如何的好几倍将适合的内部,并返回剩下值(被称为剩余部分)。bba

注意

余数operator(%)也称为其他语言的模运算符。然而,它在Swift中对负数的行为意味着,严格来说,它是一个余数而不是模运算。

以下是余数运算符的工作原理。要计算,你首先计算出适合的内部数量:449

../_images/remainderInteger_2x.png

你可以4在里面9放两个,其余的是1(用橙色表示)。

在Swift中,这将写成:

  1. 9 % 4 // equals 1

为确定答案,运算符计算以下等式并作为其输出返回:b%remainder

a=(bx )+some multiplierremainder

哪里是最适合的内部倍数。some multiplierba

插入94输入此等式可得出:

9=(42)+1

在计算负值的余数时应用相同的方法a

  1. -9 % 4 // equals -1

插入-94输入等式产生:

-9=(4-2)+-1

给出余数值-1

b对于负值,忽略符号b。这意味着并始终给出相同的答案。b-b

一元减号算子

可以使用前缀-(称为一元减号运算符)来切换数值的符号:

  1. let three = 3
  2. let minusThree = -three // minusThree equals -3
  3. let plusThree = -minusThree // plusThree equals 3, or "minus minus three"

一元减号运算符(-)直接位于它运行的值之前,没有任何空格。

一元加运算符

一元加运算+)只返回其所操作的价值,没有任何变化:

  1. let minusSix = -6
  2. let alsoMinusSix = +minusSix // alsoMinusSix equals -6

虽然一元加运算符实际上没有做任何事情,但是当使用一元减运算符作为负数时,您可以使用它来为代码提供正数的对称性。

复合赋值运算符

与C一样,Swift提供了将assignment()与另一个操作相结合的复合赋值运算符=。一个例子是加法赋值运算符+=):

  1. var a = 1
  2. a += 2
  3. // a is now equal to 3

表达式是简写。实际上,添加和分配组合成一个同时执行两个任务的操作员。+= 22

注意

复合赋值运算符不返回值。例如,你不能写。let += 2

有关Swift标准库提供的运算符的信息,请参阅运算符声明

比较运算符

Swift支持所有标准C 比较运算符

  • 等于()== b
  • 不等于()!= b
  • 大于()b
  • 小于()b
  • 大于或等于()>= b
  • 小于或等于()<= b

注意

Swift还提供了两个标识运算符===!==),用于测试两个对象引用是否都引用同一个对象实例。有关更多信息,请参阅Identity Operators

每个比较运算符都返回一个Bool值,以指示该语句是否为true:

  1. 1 == 1 // true because 1 is equal to 1
  2. 2 != 1 // true because 2 is not equal to 1
  3. 2 > 1 // true because 2 is greater than 1
  4. 1 < 2 // true because 1 is less than 2
  5. 1 >= 1 // true because 1 is greater than or equal to 1
  6. 2 <= 1 // false because 2 is not less than or equal to 1

比较运算符通常用于条件语句,例如if语句:

  1. let name = "world"
  2. if name == "world" {
  3. print("hello, world")
  4. } else {
  5. print("I'm sorry \(name), but I don't recognize you")
  6. }
  7. // Prints "hello, world", because name is indeed equal to "world".

有关该if语句的更多信息,请参阅控制流

如果它们具有相同的类型和相同的值,则可以比较两个元组。元组从左到右进行比较,一次一个值,直到比较找到两个不相等的值。比较这两个值,并且该比较的结果确定元组比较的总体结果。如果所有元素都相等,则元组本身是相等的。例如:

  1. (1, "zebra") < (2, "apple") // true because 1 is less than 2; "zebra" and "apple" are not compared
  2. (3, "apple") < (3, "bird") // true because 3 is equal to 3, and "apple" is less than "bird"
  3. (4, "dog") == (4, "dog") // true because 4 is equal to 4, and "dog" is equal to "dog"

在上面的示例中,您可以在第一行上看到从左到右的比较行为。因为1小于2,被认为小于,不管元组中的任何其他值。这不要紧,不小于,因为比较已经由元组的第一个元素决定。但是,当元组的第一个元素相同时,它们的第二个元素会比较 - 这就是第二行和第三行发生的情况。(1, "zebra")(2, "apple")"zebra""apple"

仅当运算符可以应用于相应元组中的每个值时,才能将元组与给定运算符进行比较。例如,如下面的代码所示,您可以比较两个类型的元组,因为可以使用运算符比较两者和值。相反,两个类型的元组无法与运算符进行比较,因为运算符不能应用于值。(String, Int)StringInt<(String, Bool)<<Bool

  1. ("blue", -1) < ("purple", 1) // OK, evaluates to true
  2. ("blue", false) < ("purple", true) // Error because < can't compare Boolean values

注意

Swift标准库包含元组的元组比较运算符,少于7个元素。要将元组与七个或更多元素进行比较,您必须自己实现比较运算符。

三元条件算子

所述三元条件算子是由三个部分组成,这需要形式的特殊操作。它是根据是真还是假来评估两个表达式之一的快捷方式。如果为true,则计算并返回其值; 否则,它会评估并返回其值。question answer1 answer2questionquestionanswer1answer2

三元条件运算符是以下代码的简写:

  1. if question {
  2. answer1
  3. } else {
  4. answer2
  5. }

这是一个例子,它计算表格行的高度。如果行具有标题,则行高度应比内容高度高50个点,如果行没有标题,则行高度应高20个点:

  1. let contentHeight = 40
  2. let hasHeader = true
  3. let rowHeight = contentHeight + (hasHeader ? 50 : 20)
  4. // rowHeight is equal to 90

上面的示例是以下代码的简写:

  1. let contentHeight = 40
  2. let hasHeader = true
  3. let rowHeight: Int
  4. if hasHeader {
  5. rowHeight = contentHeight + 50
  6. } else {
  7. rowHeight = contentHeight + 20
  8. }
  9. // rowHeight is equal to 90

第一个示例使用三元条件运算符意味着rowHeight可以在单行代码上设置正确的值,这比第二个示例中使用的代码更简洁。

三元条件运算符提供了一种有效的简写,用于决定要考虑两个表达式中的哪一个。但是,请谨慎使用三元条件运算符。如果过度使用,它的简洁性会导致难以阅读的代码。避免将三元条件运算符的多个实例组合到一个复合语句中。

Nil-Coalescing运算符

零-合并运算符()进行解包的可选,如果它包含一个值,或者返回一个默认值,如果是。表达式始终是可选类型。表达式必须与存储在其中的类型匹配。?? babanilaba

nil-coalescing运算符是下面代码的简写:

  1. a != nil ? a! : b

上面的代码使用三元条件操作和强制解包(a!)来访问内部包裹的值aa是不nil,并返回b,否则。nil-coalescing运算符提供了一种更简洁的方式来以简洁易读的形式封装此条件检查和解包。

注意

如果值为anilb则不评估值。这被称为短路评估

下面的示例使用nil-coalescing运算符在默认颜色名称和可选的用户定义颜色名称之间进行选择:

  1. let defaultColorName = "red"
  2. var userDefinedColorName: String? // defaults to nil
  3. var colorNameToUse = userDefinedColorName ?? defaultColorName
  4. // userDefinedColorName is nil, so colorNameToUse is set to the default of "red"

userDefinedColorName变量被定义为可选的String,具有默认值nil。因为userDefinedColorName是可选类型,您可以使用nil-coalescing运算符来考虑其值。在上面的示例中,运算符用于确定String被调用变量的初始值colorNameToUse。因为userDefinedColorNamenil,表达式返回值,或。userDefinedColorName ?? defaultColorNamedefaultColorName"red"

如果为非nil值赋值userDefinedColorName并再次执行nil-coalescing运算符检查,userDefinedColorName则使用包含在内的值而不是默认值:

  1. userDefinedColorName = "green"
  2. colorNameToUse = userDefinedColorName ?? defaultColorName
  3. // userDefinedColorName is not nil, so colorNameToUse is set to "green"

范围运算符

Swift包含多个范围运算符,它们是表示一系列值的快捷方式。

闭区域操作员

封闭范围操作符a...b)限定了从运行范围ab,并且包括这些值ab。值a不得大于b

当在您希望使用所有值的范围内进行迭代时,闭环范围运算符非常有用,例如使用forin循环:

  1. for index in 1...5 {
  2. print("\(index) times 5 is \(index * 5)")
  3. }
  4. // 1 times 5 is 5
  5. // 2 times 5 is 10
  6. // 3 times 5 is 15
  7. // 4 times 5 is 20
  8. // 5 times 5 is 25

有关forin循环的更多信息,请参阅控制流

半开放式操作员

所述半开区间运算符a..<b)限定了从运行范围ab,但不包括b。它被认为是半开放的,因为它包含它的第一个值,但不是它的最终值。与闭区域运算符一样,值a不得大于b。如果值a等于b,则结果范围将为空。

当您使用基于零的列表(如数组)时,半开范围特别有用,其中计算列表的长度(但不包括)非常有用:

  1. let names = ["Anna", "Alex", "Brian", "Jack"]
  2. let count = names.count
  3. for i in 0..<count {
  4. print("Person \(i + 1) is called \(names[i])")
  5. }
  6. // Person 1 is called Anna
  7. // Person 2 is called Alex
  8. // Person 3 is called Brian
  9. // Person 4 is called Jack

请注意,该数组包含四个项目,但0..<count只计算3(数组中最后一项的索引),因为它是半开放范围。有关数组的更多信息,请参阅数组

单面范围

闭区域运算符有一个替代形式,用于在一个方向上尽可能继续的范围 - 例如,包括从索引2到数组末尾的数组的所有元素的范围。在这些情况下,您可以省略范围运算符一侧的值。这种范围称为单侧范围,因为操作员仅在一侧具有值。例如:

  1. for name in names[2...] {
  2. print(name)
  3. }
  4. // Brian
  5. // Jack
  6. for name in names[...2] {
  7. print(name)
  8. }
  9. // Anna
  10. // Alex
  11. // Brian

半开放范围操作符也具有单侧形式,仅使用其最终值编写。就像在两侧都包含值一样,最终值不是范围的一部分。例如:

  1. for name in names[..<2] {
  2. print(name)
  3. }
  4. // Anna
  5. // Alex

单边范围可以在其他上下文中使用,而不仅仅在下标中使用。您不能迭代忽略第一个值的单侧范围,因为不清楚迭代应该从哪里开始。您可以迭代忽略其最终值的单侧范围; 但是,因为范围无限期地继续,请确保为循环添加显式结束条件。您还可以检查单侧范围是否包含特定值,如下面的代码所示。

  1. let range = ...5
  2. range.contains(7) // false
  3. range.contains(4) // true
  4. range.contains(-1) // true

逻辑运算符

逻辑运算符修改或组合布尔逻辑值truefalse。Swift支持基于C语言的三个标准逻辑运算符:

  • 逻辑NOT(!a
  • 逻辑AND()&& b
  • 逻辑OR()|| b

逻辑非运算符

逻辑非运算符!a)反转一个布尔值,使得true成为false,和falsetrue

逻辑NOT运算符是前缀运算符,并且在它运行的值之前立即出现,没有任何空格。它可以读作“not a”,如下例所示:

  1. let allowedEntry = false
  2. if !allowedEntry {
  3. print("ACCESS DENIED")
  4. }
  5. // Prints "ACCESS DENIED"

该短语可以读作“如果不允许输入。”后续行仅在“不允许输入”为真时执行; 也就是说,如果是。if !allowedEntryallowedEntryfalse

在此示例中,仔细选择布尔常量和变量名称有助于保持代码的可读性和简洁性,同时避免双重否定或混淆逻辑语句。

逻辑AND运算符

逻辑AND运算符()创建逻辑表达式,其中这两个值必须为整体表达也有。&& btruetrue

如果任一值false,则整体表达式也将是false。实际上,如果第一个值是false,则第二个值甚至不会被计算,因为它不可能使整个表达式等于true。这被称为短路评估

此示例考虑两个Bool值,并且只有两个值都允许访问true

  1. let enteredDoorCode = true
  2. let passedRetinaScan = false
  3. if enteredDoorCode && passedRetinaScan {
  4. print("Welcome!")
  5. } else {
  6. print("ACCESS DENIED")
  7. }
  8. // Prints "ACCESS DENIED"

逻辑OR运算符

逻辑OR运算符()是来自两个相邻管字符制成中缀运算符。您可以使用它来创建逻辑表达式,其中只有一个两个值必须是对整个表达式是。|| btruetrue

与上面的逻辑AND运算符一样,逻辑OR运算符使用短路评估来考虑其表达式。如果逻辑OR表达式的左侧是true,则不评估右侧,因为它不能更改整个表达式的结果。

在下面的示例中,第一个Bool值(hasDoorKey)是false,但第二个值(knowsOverridePassword)是true。因为一个值是true,整个表达式也会计算为true,并允许访问:

  1. let hasDoorKey = false
  2. let knowsOverridePassword = true
  3. if hasDoorKey || knowsOverridePassword {
  4. print("Welcome!")
  5. } else {
  6. print("ACCESS DENIED")
  7. }
  8. // Prints "Welcome!"

结合逻辑运算符

您可以组合多个逻辑运算符来创建更长的复合表达式:

  1. if enteredDoorCode && passedRetinaScan || hasDoorKey || knowsOverridePassword {
  2. print("Welcome!")
  3. } else {
  4. print("ACCESS DENIED")
  5. }
  6. // Prints "Welcome!"

此示例使用multiple &&||运算符创建更长的复合表达式。然而,&&||运算符仍然只运行两个值,所以这实际上是三个较小的表达式链接在一起。该示例可以理解为:

如果我们输入了正确的门禁密码并通过了视网膜扫描,或者我们有一个有效的门钥匙,或者我们知道紧急覆盖密码,那么允许访问。

基于,和的值enteredDoorCode,前两个子表达式是。但是,紧急覆盖密码是已知的,因此整个复合表达式仍然评估为。passedRetinaScanhasDoorKeyfalsetrue

注意

迅捷逻辑运算符&&||是左结合,这意味着与多个逻辑运算符复合表达式首先评估最左边的子表达式。

明确的括号

当它们不是严格需要时包括括号有时是有用的,以使复杂表达的意图更容易阅读。在上面的门访问示例中,在复合表达式的第一部分周围添加括号以使其意图显式是有用的:

  1. if (enteredDoorCode && passedRetinaScan) || hasDoorKey || knowsOverridePassword {
  2. print("Welcome!")
  3. } else {
  4. print("ACCESS DENIED")
  5. }
  6. // Prints "Welcome!"

括号清楚地表明前两个值被视为整体逻辑中单独可能状态的一部分。复合表达式的输出不会改变,但读者的整体意图更清晰。可读性始终优于简洁; 使用括号,帮助他们明确你的意图。

转载于:https://www.cnblogs.com/strengthen/p/9720408.html

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值