swift

Swift中强大的模式匹配

2018-05-17  本文已影响74人  小凉介

Swift中的模式匹配语法是一个亮点,Swift里switch比OC里面强大很多,switch的主要特性就是模式匹配,所以本文会主要结合switch来讲强大好用的模式匹配。

swift中模式有以下几种:

通配符模式

如果在Swift中使用了_通配符,就表示你是使用了通配符模式,_用于匹配并忽略任何值。这又分为两种情况:

    enum Moblie {
        case Man(name: String, age: Int, height: Int?)
        case Woman(name: String, age: Int, height: Int?)
    }
    
    let Roy = Moblie.Man(name: "Roy", age: 27, height: 178)
    
    switch Roy {
    case .Man(name: let name, age: let age, height: let height):
        print("\(name) -- \(age) -- \(String(describing: height))")
    default:
        break
    }

    switch Roy {
    case .Man(name: let name, age: _, height: _?):
        print("\(name)")
    default:
        break
    }

标识符模式

匹配一个具体的值或者定义变量或者常量时候,可以认为变量名和常量名就是一个标识符模式,用于接收和匹配一个特定类型的值。这种比较简单。

let i = 21 // i 就是一个标识符模式

值绑定模式

值绑定在if语句和switch语句中用的较多

    switch Roy {
    case .Man(name: let name, age: let age, height: let height):
        print("\(name) -- \(age) -- \(String(describing: height))")
    default:
        break
    }

也可以这样写

    switch Roy {
    case let .Man(name: name, age: age, height: height):
        print("\(name) -- \(age) -- \(String(describing: height))")
    default:
        break
    }

元组模式

    let error = (statusCode: 404, statusMessage: "Not Found")
            
    switch error {
    case (let code, _):
        print("\(code)")
    default:
        break
    }

这个是在详解 Swift 模式匹配中看到的示例,很赞

    let age = 23
    let job: String? = "Operator"
    let payload: AnyObject = NSDictionary()
    
    switch (age, job, payload) {
      case (let age, _?, _ as NSDictionary):
      print(age)
      default: ()
    }

枚举用例模式

    enum Result {
        case error(String)
        case image(UIImage)
        case data(Data)
    }
    
    let result = Result.error("没有找到资源")
    
    switch result {
    case let .image(image):
        print(image)
    case let .data(data):
        print(data)
    case .error(let err):
        print("Failed; error message is \(err)")
    }

可选模式

可选模式就是包含可选变量定义模式,在 if casefor caseswitch-case 会用到。注意 if case letif let的区别

    // 使用可选模式匹配
    if case let x? = someOptional {
        print(x)
    }
    
    let arrayOfOptionalInts: [Int?] = [nil, 2, 3, nil, 5]
    // 只匹配非 nil 的元素
    for case let number? in arrayOfOptinalInts {
        print("Found a \(number)")
    }
    // Found a 2
    // Found a 3
    // Found a 5
    let count: Int? = 5
    switch count {
    case 1?:
      print("1")
    case 3?:
      print("3")
    case 5?:
      print("5")
    case _:
      print("nil")
    default:
      break
    }

类型转换模式

    let a: Any = 5
    switch a {
        // 这会失败因为它的类型仍然是 `Any`
    // 错误: binary operator '+' cannot be applied to operands of type 'Any' and 'Int'
    case is Int: print (a + 1)
    // 有效并返回 '6'
    case let n as String: print ("result: "+n)
    default: ()
    }

表达式模式

可以把 switch 的值和实现了 ~= 操作符的表达式进行匹配

    let point = (1, 2)
    switch point {
    case (0, 0):
        print("(0, 0) is at the origin.")
    case (-2...2, -2...2):
        print("(\(point.0), \(point.1)) is near the origin.")
    default:
        print("The point is at (\(point.0), \(point.1)).")
    }
    struct Score {
        let Math: Int
        let Chinese: Int
        let English: Int
    }
    
    func ~= (pattern: Int, value: Score) -> Bool {
        return value.Math > pattern && value.Chinese > pattern && value.English > pattern
    }
    
    
    let score = Score(Math: 80, Chinese: 40, English: 70)
            
    switch score {
    case 90:
        print("优秀")
    default:
        break
    }

其他用法

在条件中使用where语句

    let people = (age: 27, name: "karl")
    switch people {
    case (let age, _) where age > 30:
        print(age)
    default:
        break
    }

if case let

当只有一个条件的时候,用switch会显得冗余,直接用if case let会使代码读起来更便捷。

   let Roy = Moblie.Man(name: "Roy", age: 27, height: 178)
           
   if case let .Man(name, _, _?) = Roy {
       print(name)
   }

for case let

let array: [Any?] = [1,2,nil,4,54,65,76, ""]

输出这个数组里面大于10的数字

常规写法

for item in array {
  if let element = item as? Int, element > 10 {

  }
}

for case写法

for case let x? as Int? in array where x > 10 {
  print(x)
}

用Moblie作为例子

let Roy = Moblie.Man(name: "Roy", age: 27, height: 178)
let Kelly = Moblie.Woman(name: "Kelly", age: 28, height: nil)
let Frank = Moblie.Man(name: "Frank", age: 29, height: nil)
let Arvin = Moblie.Man(name: "Arvin", age: 28, height: nil)

let moblieArray = [Roy, Kelly, Frank, Arvin]
    
for case let .Man(name, age, _?) in moblieArray where age < 29 {
    print(name)
}

参考文章:

Swift中的模式匹配
详解 Swift 模式匹配

上一篇下一篇

猜你喜欢

热点阅读