Scala模式匹配的技巧

相信每个scala程序员都有用过模式匹配。 在scala 中模式匹配也是非常强的。 下面我们来看看模式匹配的8个用法:

 

1. List Extractors:

下面看下代码实例:

val countingList = List(1,2,3,200)

// 我们可以提取这个list中的任意值
val mustHaveThree = countingList match {

    case List(_,_,3,somethingElse) => s "this list contains 3, the forth is $somethingElse"
}

以上的模式匹配会匹配到一个含有4个元素的list, 其中我们并不关心前两个元素, 但是第三个元素必须是3, 第四个元素我们可以在interpolated string 中提取。

2. haskell-like prepending

我们同样可以提取以上list的头元素和尾元素:

val startsWithOne = countingList match {
    case 1 :: someOtherElements => "the list starts with 1. the rest is $someOtherElements"
}

def processList(numbers: List[Int]): String = numbers match  {
    case Nil => ""
    case h :: t => h + "" + processList(t)
}

3. List vararg pattern

在事例一中, 我们匹配了4个元素, 可如果我们不知道整个list有多少元素的话, 我们就可以使用 list vararg 模式:

val dontCareAboutTheRest = countingList match {
    case List(_,2,_*) => "I only care that this list has 2 as second element"
}

_* 是一个非常重要的部分, 它代表了任意个数的元素。这中模式匹配会非常的灵活, 因为我们可以匹配任意个数的元素。

需要注意的是 _* 必须要在最后一个元素。 List(_,2,_*,55) 这种是错误的。

4. Other list infix patterns

我们之前匹配了第一个元素, 但是有时候我们想匹配最后一个元素, 这时候我们可以:

val mustEndWithMeaningOfLife = countingList match {
    case List(1,2,_) :+ 120 => "the last element is 120"
}

val mustEndWithMeaningOfList2 = countingList match {
    case List(1,_*) :+ 120 => "I do not care what coms before 120"
}

5. Type specifiers

我们不仅可以值匹配, 还可以进行类型匹配

def gimmeAValue(): Any = {...}
val gimmeTheType = gimmeAValue() match {
    case _:String => "this method returns String"
    case _:Int => "this method returns Int"
    case _ => "this method returns something else"
}

try {...} catch {
    case _:IOException => "IO failed"
    case _:Exception => "we could have prevented that"
    case _:RuntimeException => "something else crashed"
}

这种类型匹配会用到反射, 所以可能会有一些性能的影响。

6. Name binding

def requestMoreInfo(p: Person): String = { ... } 

val bob = Person("Bob", 34, List("Inception", "The Departed")) 

val bobsInfo = bob match { 
    case Person(name, age, movies) => 
        s"$name's info: ${requestMoreInfo(Person(name, age, movies))}" 
}

// 我们使用 p @ 来命名
val bobsInfo = bob match { 
    case p @ Person(name, _, _) => s"$name's info: ${requestMoreInfo(p)}" 
}

val bobsInception = bob match { 
    case Person(name, _, movies @ List("Inception", _*)) => 
        s"$name REALLY likes Inception, some other movies too: $movies" 
}

7. Conditional guards

我们可以在pattern mattern中使用if 条件语句

val ordinal = gimmeANumber() match { 
    case 1 => "first" 
    case 2 => "second" 
    case 3 => "third" 
    case n if n % 10 == 1 => n + "st" 
    case n if n % 10 == 2 => n + "nd" 
    case n if n % 10 == 3 => n + "rd" 
    case n => n + "th" 
}

8. Alternative patterns

如果有多个case 返回同样的结果, 我们可以使用 ‘|’ 来拼接这些case, 类似于 “或”

val myOptimalList = numbers match { 
    case List(1, _, _) | List (43, _*) => "I like this list" 
    case _ => "I don't like it" 
}

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值