博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
Swift中的模式匹配
阅读量:5818 次
发布时间:2019-06-18

本文共 4964 字,大约阅读时间需要 16 分钟。

模式匹配

模式匹配是 Swift 中非常常见的一种编程模式,使用模式匹配,可以帮助我们写出简明、清晰以及易读的代码,使我们的代码变得简洁而强大。

条件判断中的模式匹配

条件判断是我们使用最普遍的流程控制,在 Swift 中,只能接受 Bool 类型的值作为条件体;除了直接判断 Bool 值之外,我们还能使用使用条件语句进行可选绑定,这在我们开发中是非常常用的方式。

匹配枚举值

在 Swift 中,创建的枚举类型默认是不可比较的(没有实现Comparable协议),这就意味着我们不能直接使用==操作符来判断两个枚举值是否相等,这种情况下,需要使用模式匹配:

创建一个枚举类型:

enum Result {    case success    case failure}复制代码

初始化一个枚举值:

let result = Result.success复制代码

使用模式匹配来判断创建的枚举值的值:

if case .success = result {    print("Value of result is success.")}复制代码

可选绑定

创建一个可选值:

let optionalInt: Int? = 1复制代码

使用可选绑定的方式进行解包:

if let val = optionalInt {    print("The value of optionalInt is (val)")}func handleGuard() {    guard let val = optionalInt else {        return    }    print("The value of optionalInt is (val)")}handleGuard()复制代码

可选绑定的另外一种模式,这也是可选绑定中最基础的模式:

if case .some(let val) = optionalInt {    print("The value of optionalInt is (val)")}复制代码

还可以简化为:

if case let val? = optionalInt {    print("The value of optionalInt is (val)")}复制代码

循环中的模式匹配

问题来了,if let 模式的可选绑定,只能实现一个可选值的绑定,如果我们需要匹配一个数组里边的可选值怎么办呢?这时候我们就不能使用 if let 的形式了,需要使用到 if case let 的形式

创建一个包含可选值的数组:

let values: [Int?] = [1, nil, 3, nil, 5, nil, 7, nil, 9, nil]复制代码

进行遍历:

for val in values {    print("Value in values is (String(describing: val))")}复制代码

或者:

var valuesIterator = values.makeIterator()while let val = valuesIterator.next() {    print("Value in values is (String(describing: val))")}复制代码

我们得到了所有的值与可选值,如果我们需要过滤可选值,我们可以这样做:

for val in values.compactMap({ $0 }) {    print("Value in values is (val)")}复制代码

这样做,增加了时间复杂度,需要进行两次遍历才能将数据过滤出来。我们可以使用模式匹配的方式来这样做:

for case let val? in values {    print("Value in values is (val)")}复制代码

或者:

valuesIterator = values.makeIterator()while let val = valuesIterator.next(), val != nil {    print("Value in values is (String(describing: val))")}复制代码

这样就可以将 nil 值给过滤了,是不是很简单?还可以使用 for case 匹配枚举值数组:

let results: [Result] = [.success, .failure]for case .success in results {    print("Values in results contains success.")    break}复制代码

对于复杂的枚举类型:

enum NetResource {    case http(resource: String)    case ftp(resource: String)}let nets: [NetResource] = [.http(resource: "https://www.baidu.com"), .http(resource: "https://www.apple.cn"), .ftp(resource: "ftp://192.0.0.1")]复制代码

过滤 http 的值:

for case .http(let resource) in nets {    print("HTTP resource (resource)")}复制代码

for 循环使用 where 从句

除此之外,我们还可以在 for 循环后边跟上一个 where 从句来进行模式匹配:

for notNilValue in values where notNilValue != nil {    print("Not nil value: (String(describing: notNilValue!))")}复制代码

查询一个数组里边所有能被3整除的数:

let rangeValues = Array(0...999)for threeDivideValue in rangeValues where threeDivideValue % 3 == 0 {    print("Three devide value: (threeDivideValue)")}复制代码

查询所有含有3的数:

for containsThree in rangeValues where String(containsThree).contains("3") {    print("Value contains three: (containsThree)")}复制代码

Switch 中的模式匹配

Switch 中的模式匹配也很常用,在 Switch 中合理地使用模式匹配可以为我们带来很多好处,可以使我们的代码更简洁,同时可以减少代码量和增加开发效率。

区间匹配

let value = 188switch value {case 0..<50:    print("The value is in range [0, 50)")case 50..<100:    print("The value is in range [50, 100)")case 100..<150:    print("The value is in range [100, 150)")case 150..<200:    print("The value is in range [150, 200)")case 200...:    print("The value is in range [200, ")default: break}// The value is in range [150, 200)复制代码

匹配元组类型

创建一个元组类型:

let tuples: (Int, String) = (httpCode: 404, status: "Not Found.")复制代码

进行匹配:

switch tuples {case (400..., let status):    print("The http code is 40x, http status is (status)")default: break}复制代码

创建一个点:

let somePoint = (1, 1)复制代码

进行匹配:

switch somePoint {case (0, 0):    print("(somePoint) is at the origin")case (_, 0):    print("(somePoint) is on the x-axis")case (0, _):    print("(somePoint) is on the y-axis")case (-2...2, -2...2):    print("(somePoint) is inside the box")default:    print("(somePoint) is outside of the box")}复制代码

如上,我们在匹配的时候可以使用下划线 _ 对值进行忽略:

switch tuples {case (404, _):    print("The http code is 404 not found.")default: break}复制代码

switch case 中使用 where 从句

在 case 中使用 where 从句可以使我们的模式匹配看起来更加精简,使匹配的模式更加紧凑:

let yetAnotherPoint = (1, -1)switch yetAnotherPoint {case let (x, y) where x == y:    print("((x), (y)) is on the line x == y")case let (x, y) where x == -y:    print("((x), (y)) is on the line x == -y")case let (x, y):    print("((x), (y)) is just some arbitrary point")}复制代码

总结

Swift 中模式匹配的种类

模式匹配可以说是 Swift 中非常强大的一种编程模式,使用良好的模式匹配,可以帮助我们写出简介、优雅的代码,Swift 中的模式匹配包括以下种类:

  • 条件判断:if, guard
  • 可选绑定:if let, guard let, while let ...
  • 循环体:for, while, repeat while
  • switch
  • do catch

什么时候使用 where 从句?

我们可以在前文的例子中看到,在很多进行模式匹配的地方还使用了 where 从句,where 从句的作用就相当于在模式匹配的基础上在加上条件限制,使用 where 从句等价于:

for notNilValue in values {    if notNilValue != nil {        print("Not nil value: (String(describing: notNilValue!))")    }}复制代码

可以看出,使用 where 从句可以使我们的代码更加简洁和易读,什么时候使用 where ? 或者说在哪里可以使用 where ? Swift 文档中并没有对 where 的详细使用进行介绍,但是在实践中发现,where 可以使用在以下地方:

  • for 循环语句
  • switch 分支

而对于 if, guardwhile ,我们不能在其后面添加 where 从句,因为他们本身可以进行多个条件的组合. where 从句还有一个用法就是对泛型类型进行类型约束,这在泛型的章节中会有介绍.

转载地址:http://bzzdx.baihongyu.com/

你可能感兴趣的文章
Linux 目录结构及内容详解
查看>>
OCP读书笔记(24) - 题库(ExamD)
查看>>
解决Unable to load R3 module ...VBoxDD.dll (VBoxDD):GetLastError=1790
查看>>
.net excel利用NPOI导入oracle
查看>>
$_SERVER['SCRIPT_FLENAME']与__FILE__
查看>>
My97DatePicker 日历插件
查看>>
hive基本操作与应用
查看>>
excel快捷键设置
查看>>
poj3692
查看>>
html5纲要,细谈HTML 5新增的元素
查看>>
Android应用集成支付宝接口的简化
查看>>
[分享]Ubuntu12.04安装基础教程(图文)
查看>>
django 目录结构修改
查看>>
win8 关闭防火墙
查看>>
CSS——(2)与标准流盒模型
查看>>
MYSQL 基本SQL语句
查看>>
C#中的Marshal
查看>>
linux命令:ls
查看>>
Using RequireJS in AngularJS Applications
查看>>
hdu 2444(二分图最大匹配)
查看>>