Swift中的模式匹配

模式匹配

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

条件判断中的模式匹配

条件判断是咱们使用最广泛的流程控制,在 Swift 中,只能接受 Bool 类型的值做为条件体;除了直接判断 Bool 值以外,咱们还能使用使用条件语句进行可选绑定,这在咱们开发中是很是经常使用的方式。github

匹配枚举值

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

建立一个枚举类型:swift

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

初始化一个枚举值:数组

let result = Result.success
复制代码

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

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

可选绑定

建立一个可选值:ide

let optionalInt: Int? = 1
复制代码

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

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()
复制代码

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

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

还能够简化为:code

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 = 188

switch 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 从句还有一个用法就是对泛型类型进行类型约束,这在泛型的章节中会有介绍.

原文地址

相关文章
相关标签/搜索