当前位置: 代码迷 >> 综合 >> Scala模式匹配的技巧
  详细解决方案

Scala模式匹配的技巧

热度:60   发布时间:2024-02-22 16:09:42.0

相信每个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" 
}