9、Swift 中的控制流与函数详解

Swift 中的控制流与函数详解

1. switch 语句

switch 语句会获取一个值,然后将其与多个可能的匹配项进行比较,并根据第一个成功的匹配执行相应的代码块。它是在有多个可能匹配项时替代 if - else 语句的一种选择。其格式如下:

switch value {
  case match1 :
    block of code
  case match2 :
    block of code
  …… as many cases as needed
  default :
    block of code
}

与大多数其他语言中的 switch 语句不同,在 Swift 中,它不会贯穿到下一个 case 语句,因此不需要使用 break 语句来防止贯穿。这是 Swift 内置的一项安全特性,因为初学者在使用 switch 语句时最常见的编程错误之一就是忘记在 case 语句末尾添加 break 语句。

以下是一个使用 switch 语句的示例:

var speed = 300000000
switch speed {
case 300000000:
    print("Speed of light")
case 340:
    print("Speed of sound")
default:
    print("Unknown speed")
}

在上述示例中,switch 语句获取 speed 变量的值,并将其与两个 case 语句进行比较。如果 speed 的值与任何一个 case 匹配,它将输出该速度的信息。如果没有找到匹配项,则输出 “Unknown speed” 消息。

每个 switch 语句必须涵盖所有可能的值。这意味着除非是与枚举进行匹配,否则每个 switch 语句都必须有一个 default case。例如:

var num = 5
switch num {
case 1 :
    print("number is one")
case 2 :
    print("Number is two")
case 3 :
    print("Number is three")
}

如果将上述代码放入 Playground 并尝试编译,会收到 “switch must be exhaustive, consider adding a default clause” 错误。这是一个编译时错误,只有在尝试编译代码时才会被通知。

可以在单个 case 中包含多个项目,只需用逗号分隔这些项目即可。例如,判断一个字符是元音还是辅音:

var char : Character = "e"
switch char {
case "a", "e", "i", "o", "u":
    print("letter 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":
    print("letter is a consonant")
default:
    print("unknown letter")
}

还可以使用范围运算符来检查 switch 语句的值是否包含在某个范围内。例如:

var grade = 93
switch grade {
case 90...100:
    print("Grade is an A")
case 80...89:
    print("Grade is a B")
case 70...79:
    print("Grade is an C")
case 60...69:
    print("Grade is a D")
case 0...59:
    print("Grade is a F")
default:
    print("Unknown Grade")
}

在 Swift 中,任何 case 语句都可以包含一个可选的 guard 条件,以提供额外的验证条件。guard 条件使用 where 关键字定义。例如:

var studentId = 4
var grade = 57
switch grade {
case 90...100:
    print("Grade is an A")
case 80...89:
    print("Grade is a B")
case 70...79:
    print("Grade is an C")
case 55...69 where studentId == 4:
    print("Grade is a D for student 4")
case 60...69:
    print("Grade is a D")
case 0...59:
    print("Grade is a F")
default:
    print("Unknown Grade")
}

需要注意的是,Swift 会从第一个 case 语句开始按顺序检查每个 case 语句。因此,如果将带有 guard 表达式的 case 语句放在 “Grade is a F” case 语句之后,那么带有 guard 表达式的 case 语句将永远不会被执行。

switch 语句在评估枚举时也非常有用。由于枚举的值是有限的,如果为枚举的所有值提供了 case 语句,则不需要提供 default case。例如:

enum Product {
    case Book(String, Double, Int)
    case Puzzle(String, Double)
}
var order = Product.Book("Mastering Swift 2", 49.99, 2015)
switch order {
case .Book(let name, let price, let year):
    print("You ordered the book \(name) for \(price)")
case .Puzzle(let name, let price):
    print("You ordered the Puzzle \(name) for \(price)")
}
2. 在条件语句中使用 case 和 where 语句

从 Swift 2 开始,可以在 if、for 和 while 等其他条件语句中使用 case 和 where 语句。在条件语句中使用这些语句可以使代码更简洁、易读。

2.1 使用 where 语句过滤 for - in 循环的结果

在不使用 where 语句过滤偶数的示例:

for number in 1…30 {
    if number % 2 == 0 {
        print(number)
    }
}

使用 where 语句过滤偶数的示例:

for number in 1...30 where number % 2 == 0 {
    print(number)
}

使用 where 语句可以减少代码行数,并且由于过滤语句与 for - in 循环在同一行,使代码更易读。

2.2 使用 for - case 语句进行过滤

以下是使用 for - case 语句过滤数组中特定元素的示例:

var worldSeriesWinners = [
    ("Red Sox", 2004),
    ("White Sox", 2005),
    ("Cardinals", 2006),
    ("Red Sox", 2007),
    ("Phillies", 2008),
    ("Yankees", 2009),
    ("Giants", 2010),
    ("Cardinals", 2011),
    ("Giants", 2012),
    ("Red Sox", 2013),
    ("Giants", 2014)
]
for case let ("Red Sox", year) in worldSeriesWinners {
    print(year)
}

该示例中,创建了一个包含元组的数组 worldSeriesWinners,每个元组包含球队名称和获胜年份。使用 for - case 语句过滤出 “Red Sox” 获胜的年份并输出。

for - case 语句还可以轻松过滤可选数组中的 nil 值。例如:

let myNumbers: [Int?] = [1, 2, nil, 4, 5, nil, 6]
for case let .Some(num) in myNumbers {
    print(num)
}

也可以将 for - case 与 where 语句结合使用进行额外过滤:

let myNumbers: [Int?] = [1, 2, nil, 4, 5, nil, 6]
for case let num? in myNumbers where num > 3 {
    print(num)
}

如果不使用 case 和 where 语句进行相同的过滤,代码如下:

for num in myNumbers {
    if let num = num {
        if num > 3 {
            print(num)
        }
    }
}

可以看出,使用 for - case 和 where 语句可以大大减少所需的代码行数,并且使代码更易读。

2.3 使用 if - case 语句

if - case 语句与 switch 语句非常相似。大多数情况下,更倾向于使用 switch 语句,但在只寻找一两个可能匹配项且不想处理所有可能匹配项时,if - case 语句更合适。例如:

enum Identifier {
    case Name(String)
    case Number(Int)
    case NoIdentifier
}
var playerIdentifier = Identifier.Number(42)
if case let .Number(num) = playerIdentifier {
    print("Player's number is \(num)")
}

同样,可以在 if - case 语句中使用 where 语句进行额外过滤:

var playerIdentifier = Identifier.Number(42)
if case let .Number(num) = playerIdentifier where num == 2 {
    print("Player is either Xander Bogarts or Derek Jeter")
}
3. 控制转移语句

Swift 提供了五种控制转移语句:continue、break、fallthrough、guard、throws 和 return。

3.1 continue 语句

continue 语句告诉循环停止执行当前代码块,并进入循环的下一次迭代。以下是一个使用 continue 语句打印范围内奇数的示例:

for i in 1...10 {
    if i % 2 == 0 {
        continue
    }
    print("\(i) is odd")
}

输出结果为:

1 is odd
3 is odd
5 is odd
7 is odd
9 is odd
3.2 break 语句

break 语句会立即结束控制流中代码块的执行。以下是一个在遇到第一个偶数时跳出 for 循环的示例:

for i in 1...10 {
    if i % 2 == 0 {
        break
    }
    print("\(i) is odd")
}

输出结果为:

1 is odd
3.3 fallthrough 语句

在 Swift 中,switch 语句不会贯穿到下一个 case 语句,但可以使用 fallthrough 语句强制贯穿。fallthrough 语句可能很危险,因为一旦找到匹配项,下一个 case 默认会被执行。例如:

var name = "Jon"
var sport = "Baseball"
switch sport {
case "Baseball":
    print("\(name) plays Baseball")
    fallthrough
case "Basketball":
    print("\(name) plays Basketball")
    fallthrough
default:
    print("Unknown sport")
}

输出结果为:

Jon plays Baseball
Jon plays Basketball
Unknown sport
3.4 guard 语句

在 Swift 2 中,Apple 引入了新的 guard 语句。它专注于在条件为 false 时执行某个功能,允许在函数早期捕获错误并执行错误处理。例如:

var x = 9
guard x > 10 else {
  // Do error condition
  return
}
// Functional code here

在上述示例中,检查变量 x 是否大于 10,如果不大于 10,则执行错误处理。如果 x 大于 10,代码继续执行。guard 语句中的代码必须包含一个控制转移语句,以防止其余代码执行。如果忘记添加控制转移语句,Swift 会显示编译时错误。

综上所述,Swift 中的控制流和函数提供了丰富的功能和灵活的语法,能够帮助开发者编写更安全、简洁和易读的代码。通过合理使用 switch 语句、case 和 where 语句以及控制转移语句,可以更好地处理各种情况和错误,提高代码的质量和可维护性。

Swift 中的控制流与函数详解(下半部分)

4. 控制流与函数的综合应用示例

为了更好地理解上述控制流和函数相关知识的实际应用,下面给出一些综合示例。

4.1 综合使用 switch 和 where 进行复杂条件判断

假设我们要根据学生的成绩和是否为特殊学生来给出不同的评价。代码如下:

enum StudentType {
    case Normal
    case Special
}

var studentType = StudentType.Special
var grade = 57
var studentId = 4

switch grade {
case 90...100:
    print("Excellent performance!")
case 80...89:
    print("Good job!")
case 70...79:
    print("Not bad, keep it up!")
case 55...69 where studentType == .Special && studentId == 4:
    print("For special student 4, this is still a passable grade.")
case 60...69:
    print("You passed, but there is room for improvement.")
case 0...59:
    print("Need to work harder.")
default:
    print("Unknown grade.")
}

在这个示例中,我们结合了枚举类型 StudentType 来区分普通学生和特殊学生,并且在 switch 语句中使用了 where 子句来对特殊学生的成绩进行额外判断。

4.2 结合 for - case 和 guard 进行数组元素处理

假设有一个包含可选整数的数组,我们要找出其中大于 5 且不为 nil 的元素,并对其进行一些操作。代码如下:

let myNumbers: [Int?] = [1, nil, 6, 3, nil, 8, 2]

for case let num? in myNumbers {
    guard num > 5 else {
        continue
    }
    print("The number \(num) meets the requirement.")
}

这里我们先使用 for - case 过滤掉 nil 值,然后使用 guard 语句进一步筛选出大于 5 的元素。

5. 控制流语句的性能考虑

在使用控制流语句时,性能也是一个需要考虑的因素。以下是一些常见控制流语句的性能特点:

控制流语句 性能特点
switch 当有多个离散值需要匹配时, switch 语句的性能通常较好,尤其是在枚举类型的匹配上。因为编译器可以对枚举类型的 switch 进行优化,直接跳转到匹配的 case 分支。
if - else 对于简单的条件判断, if - else 语句的性能是可以接受的。但如果有多个嵌套的 if - else 语句,会增加代码的复杂度和执行时间。
for - in for - in 循环在遍历数组、集合等序列时性能较好,因为它是按照顺序依次访问元素。但如果在循环体中进行复杂的操作,会影响整体性能。
while while 循环的性能取决于循环条件的判断和循环体的执行时间。如果循环条件判断复杂或者循环体执行时间长,会导致性能下降。
6. 最佳实践建议

为了编写高质量的 Swift 代码,在使用控制流和函数时,可以遵循以下最佳实践:

6.1 switch 语句
  • 确保 switch 语句覆盖所有可能的值,除非是对枚举类型进行匹配且已经为所有枚举值提供了 case 分支。
  • 当使用 guard 表达式时,将带有 guard 条件的 case 语句放在没有 guard 条件的类似 case 语句之前。
  • 在枚举类型的 switch 中,尽量避免使用 default 分支,除非确实有未处理的情况。
6.2 case 和 where 语句
  • 在条件语句中使用 case where 语句可以使代码更简洁、易读,尤其是在过滤和匹配操作中。
  • 结合 for - case where 语句可以减少嵌套的 if 语句,提高代码的可读性。
6.3 控制转移语句
  • continue 语句适用于跳过当前循环迭代中不需要执行的代码,提高循环效率。
  • break 语句用于提前终止循环或 switch 语句,避免不必要的计算。
  • fallthrough 语句要谨慎使用,因为它可能会导致代码逻辑混乱,除非确实需要强制贯穿。
  • guard 语句可以在函数开始时处理错误条件,使函数的主要逻辑更加清晰。
7. 总结

Swift 中的控制流和函数提供了丰富的工具来处理各种编程场景。 switch 语句可以方便地进行多值匹配, case where 语句可以在条件语句中进行灵活的过滤和匹配,而控制转移语句则可以精确地控制代码的执行流程。

通过合理运用这些控制流和函数的特性,开发者可以编写出更安全、简洁、易读且性能良好的代码。同时,遵循最佳实践建议可以进一步提高代码的质量和可维护性。在实际开发中,要根据具体的需求和场景选择合适的控制流语句和函数,以达到最佳的编程效果。

下面是一个简单的 mermaid 流程图,展示了 for - case where 结合使用的流程:

graph TD;
    A[开始] --> B[遍历数组元素];
    B --> C{元素是否为非 nil};
    C -- 是 --> D{元素是否满足 where 条件};
    C -- 否 --> B;
    D -- 是 --> E[处理元素];
    D -- 否 --> B;
    E --> B;
    B --> F[结束];

这个流程图清晰地展示了使用 for - case where 语句过滤数组元素的过程。首先遍历数组元素,判断元素是否为非 nil ,如果是则进一步判断是否满足 where 条件,满足则进行处理,不满足则继续遍历下一个元素,直到遍历完所有元素。

内容概要:本文提出了一种基于改进扩散模型的高海拔地区新能源高波动出力场景生成方法,并提供了完整的Python代码实现。该方法针对高海拔地区风能、光伏等新能源出力波动剧烈、不确定性高的特点,通过优化扩散模型的结构训练策略,有效捕捉历史数据的概率分布特征时序相关性,从而生成高质量、多样化的出力场景。文中详细阐述了模型的数学推导、网络架构设计、损失函数优化及采样算法改进,并通过实验证明其在拟合精度、场景多样性稳定性方面优于传统生成模型,为电力系统在高比例新能源接入下的规划、调度风险评估提供了可靠的场景输入支持。; 适合人群:具备一定Python编程能力和机器学习基础,从事新能源发电预测、电力系统分析、智能优化、场景生成等方向研究的科研人员、高校研究生及工程技术人员。; 使用场景及目标:①用于高海拔地区风电、光伏出力的不确定性建模多场景生成;②支撑含高渗透率新能源的电力系统随机优化调度、鲁棒决策风险评估;③为相关学术研究、论文复现算法改进提供可运行的技术方案代码基础; 阅读建议:建议读者结合所提供的完整资源(代码、数据集、说明文档)进行实践操作,重点关注扩散模型的前向加噪反向去噪过程的设计细节,以及如何将其适配于新能源时序数据的生成任务,通过参数调优对比实验深入理解模型的生成机制性能边界。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值