深入讲解Swift中的模式匹配
模式匹配
模式匹配是Swift中非常常见的一种编程模式,使用模式匹配,可以帮助我们写出简明、清晰以及易读的代码,使我们的代码变得简洁而强大。
条件判断中的模式匹配
条件判断是我们使用最普遍的流程控制,在Swift中,只能接受Bool类型的值作为条件体;除了直接判断Bool值之外,我们还能使用使用条件语句进行可选绑定,这在我们开发中是非常常用的方式。
匹配枚举值
在Swift中,创建的枚举类型默认是不可比较的(没有实现Comparable协议),这就意味着我们不能直接使用==操作符来判断两个枚举值是否相等,这种情况下,需要使用模式匹配:
创建一个枚举类型:
enumResult{ casesuccess casefailure }
初始化一个枚举值:
letresult=Result.success
使用模式匹配来判断创建的枚举值的值:
ifcase.success=result{ print("Valueofresultissuccess.") }
可选绑定
创建一个可选值:
letoptionalInt:Int?=1
使用可选绑定的方式进行解包:
ifletval=optionalInt{ print("ThevalueofoptionalIntis(val)") } funchandleGuard(){ guardletval=optionalIntelse{ return } print("ThevalueofoptionalIntis(val)") } handleGuard()
可选绑定的另外一种模式,这也是可选绑定中最基础的模式:
ifcase.some(letval)=optionalInt{ print("ThevalueofoptionalIntis(val)") }
还可以简化为:
ifcaseletval?=optionalInt{ print("ThevalueofoptionalIntis(val)") }
循环中的模式匹配
问题来了,iflet模式的可选绑定,只能实现一个可选值的绑定,如果我们需要匹配一个数组里边的可选值怎么办呢?这时候我们就不能使用iflet的形式了,需要使用到ifcaselet的形式
创建一个包含可选值的数组:
letvalues:[Int?]=[1,nil,3,nil,5,nil,7,nil,9,nil]
进行遍历:
forvalinvalues{ print("Valueinvaluesis(String(describing:val))") }
或者:
varvaluesIterator=values.makeIterator() whileletval=valuesIterator.next(){ print("Valueinvaluesis(String(describing:val))") }
我们得到了所有的值与可选值,如果我们需要过滤可选值,我们可以这样做:
forvalinvalues.compactMap({$0}){ print("Valueinvaluesis(val)") }
这样做,增加了时间复杂度,需要进行两次遍历才能将数据过滤出来。我们可以使用模式匹配的方式来这样做:
forcaseletval?invalues{ print("Valueinvaluesis(val)") }
或者:
valuesIterator=values.makeIterator() whileletval=valuesIterator.next(),val!=nil{ print("Valueinvaluesis(String(describing:val))") }
这样就可以将nil值给过滤了,是不是很简单?还可以使用forcase匹配枚举值数组:
letresults:[Result]=[.success,.failure] forcase.successinresults{ print("Valuesinresultscontainssuccess.") break }
对于复杂的枚举类型:
enumNetResource{ casehttp(resource:String) caseftp(resource:String) } letnets:[NetResource]=[.http(resource:"https://www.baidu.com"),.http(resource:"https://www.apple.cn"),.ftp(resource:ftp://192.0.0.1)]
过滤http的值:
forcase.http(letresource)innets{ print("HTTPresource(resource)") }
for循环使用where从句
除此之外,我们还可以在for循环后边跟上一个where从句来进行模式匹配:
fornotNilValueinvalueswherenotNilValue!=nil{ print("Notnilvalue:(String(describing:notNilValue!))") }
查询一个数组里边所有能被3整除的数:
letrangeValues=Array(0...999) forthreeDivideValueinrangeValueswherethreeDivideValue%3==0{ print("Threedevidevalue:(threeDivideValue)") }
查询所有含有3的数:
forcontainsThreeinrangeValueswhereString(containsThree).contains("3"){ print("Valuecontainsthree:(containsThree)") }
Switch中的模式匹配
Switch中的模式匹配也很常用,在Switch中合理地使用模式匹配可以为我们带来很多好处,可以使我们的代码更简洁,同时可以减少代码量和增加开发效率。
区间匹配
letvalue=188 switchvalue{ case0..<50: print("Thevalueisinrange[0,50)") case50..<100: print("Thevalueisinrange[50,100)") case100..<150: print("Thevalueisinrange[100,150)") case150..<200: print("Thevalueisinrange[150,200)") case200...: print("Thevalueisinrange[200,") default:break } //Thevalueisinrange[150,200)
匹配元组类型
创建一个元组类型:
lettuples:(Int,String)=(httpCode:404,status:"NotFound.")
进行匹配:
switchtuples{ case(400...,letstatus): print("Thehttpcodeis40x,httpstatusis(status)") default:break }
创建一个点:
letsomePoint=(1,1)
进行匹配:
switchsomePoint{ case(0,0): print("(somePoint)isattheorigin") case(_,0): print("(somePoint)isonthex-axis") case(0,_): print("(somePoint)isonthey-axis") case(-2...2,-2...2): print("(somePoint)isinsidethebox") default: print("(somePoint)isoutsideofthebox") }
如上,我们在匹配的时候可以使用下划线_对值进行忽略:
switchtuples{ case(404,_): print("Thehttpcodeis404notfound.") default:break }
在switchcase中使用where从句
在case中使用where从句可以使我们的模式匹配看起来更加精简,使匹配的模式更加紧凑:
letyetAnotherPoint=(1,-1) switchyetAnotherPoint{ caselet(x,y)wherex==y: print("((x),(y))isonthelinex==y") caselet(x,y)wherex==-y: print("((x),(y))isonthelinex==-y") caselet(x,y): print("((x),(y))isjustsomearbitrarypoint") }
总结
Swift中模式匹配的种类
模式匹配可以说是Swift中非常强大的一种编程模式,使用良好的模式匹配,可以帮助我们写出简介、优雅的代码,Swift中的模式匹配包括以下种类:
- 条件判断:if,guard
- 可选绑定:iflet,guardlet,whilelet...
- 循环体:for,while,repeatwhile
- switch
- docatch
什么时候使用where从句?
我们可以在前文的例子中看到,在很多进行模式匹配的地方还使用了where从句,where从句的作用就相当于在模式匹配的基础上在加上条件限制,使用where从句等价于:
fornotNilValueinvalues{ ifnotNilValue!=nil{ print("Notnilvalue:(String(describing:notNilValue!))") } }
可以看出,使用where从句可以使我们的代码更加简洁和易读,什么时候使用where?或者说在哪里可以使用where?Swift文档中并没有对where的详细使用进行介绍,但是在实践中发现,where可以使用在以下地方:
- for循环语句
- switch分支
而对于if,guard与while,我们不能在其后面添加where从句,因为他们本身可以进行多个条件的组合.where从句还有一个用法就是对泛型类型进行类型约束,这在泛型的章节中会有介绍.
好了,以上就是这篇文章的全部内容了,希望本文的内容对大家的学习或者工作具有一定的参考学习价值,如果有疑问大家可以留言交流,谢谢大家对毛票票的支持。