scala的模式匹配使用的 match
关键字,每个分支使用 case
进行声明,会从第一个case
语句进行匹配,匹配成功则执行相关逻辑,匹配不成功,则执行 case _
的逻辑, 如果没声明 case _
且没匹配成功,则会抛出 MatchError
的错误。
1 守卫匹配
for (ch <- "+-3!") {
var sign = 0
var digit = 0
ch match {
case _ if ch.toString.equals("3") => digit = 3
case _ if (ch > 1110 || ch < 120) => println("ch > 10")
case _ => sign = 2
}
println(ch + " " + sign + " " + digit)
}
2 变量匹配
val ch1 = '+'
//match是一个表达式,因此可以有返回值
//返回值就是匹配到的代码块的最后一句话的值
val res = ch1 match {
case '+' => ch1 + " hello "
// 下面 case mychar 含义是 mychar = ch
case _ => println ("ok~~")
}
println("res=" + res)
3 类型匹配
val obj = Map[String,Int]("age"->10)
val result = obj match {
case a: Int => a
case b: Map[String, Int] => "对象是一个字符串-数字的Map集合"
case c: Map[Int, String] => "对象是一个数字-字符串的Map集合"
case d: Array[String] => d //"对象是一个字符串数组"
case e: Array[Int] => "对象是一个数字数组"
case _ =>
}
println(result)
4 匹配数组
val arrs2 = Array(Array(0), Array(1, 0), Array(0, 1, 0),
Array(1, 1, 0), Array(1, 1, 0, 1))
for (arr <- arrs2 ) {
val result = arr match {
case Array(x, y) => ArrayBuffer(y,x) // 匹配有两个元素的数组,并变换数组的位置
case Array(0, _*) => "以0开头和数组" // 匹配以 0 开头的数组
case _ =>
}
println("res=" + result)
}
5 匹配列表
case 语句中置符,两个元素间的 ::
叫中置表达式,至少需要两个 second,first才能匹配
for (list <- Array(List(0), List(1, 0), List(88), List(0, 0, 0), List(1, 0, 0))) {
val result = list match {
case 0 :: Nil => "0" //
case x :: y :: Nil => x + " " + y //
case 0 :: tail => "0 ..." //
case x :: Nil => x
case _ => "something else"
}
println(result)
}
val array = List("hello","world","hello","scala")
array match {
case first::second::rest => println("first="+first,"second="+second,"rest="+rest)
case _ =>
}
6 匹配元组
for (pair <- Array((0, 1), (1, 0), (10, 30), (1, 1), (1, 0, 2))) {
val result = pair match { //
case (0, _) => "0 ..." // 匹配以 0开头的元组
case (y, 0) => y // 匹配以0结尾的元组
case (x, y) => (y, x) //"匹配到(x,y)" + x + " " + y
case _ => "other" //.
}
7 匹配对象
val number: Double = Square(5.0)// 36.0 //
number match {
//说明 case Square(n) 的运行的机制
//1. 当匹配到 case Square(n)
//2. 调用Square 的 unapply(z: Double),z 的值就是 number
//3. 如果对象提取器 unapply(z: Double) 返回的是Some(6) ,则表示匹配成功,同时
// 将6 赋给 Square(n) 的n
//4. 果对象提取器 unapply(z: Double) 返回的是None ,则表示匹配不成功
case Square(n) => println("匹配成功 n=" + n)
case _ => println("nothing matched")
}
object Square {
def unapply(z: Double): Option[Double] = {
println("unapply被调用 z 是=" + z)
Some(math.sqrt(z))
}
def apply(z: Double): Double = z * z
}
object SalesDem0 {
def main(args: Array[String]): Unit = {
//这里给出了一个具体的打折的案例
// 120.
val sale = Bundle("书籍", 10, Book("漫画", 40), Bundle("文学作品", 20, Book("《阳关》", 80), Book("《围城》", 30),Book("天龙八部", 100)))
//知识点1 - 使用case语句,得到 "漫画"
val res = sale match {
//如果我们进行对象匹配时,不想接受某些值,则使用_ 忽略即可,_* 表示所有
case Bundle(_, _, Book(desc, _), _*) => desc
}
println("res=" + res) //
//知识点2-通过@表示法将嵌套的值绑定到变量。_*绑定剩余Item到rest
val res2 = sale match {
//如果我们进行对象匹配时,不想接受某些值,则使用_ 忽略即可,_* 表示所有
case Bundle(_, _, art @ Book(_, _), rest @ _*) => (art, rest)
}
println("res2=" + res2)
//知识点3-不使用_*绑定剩余Item到rest
val res3 = sale match {
//如果我们进行对象匹配时,不想接受某些值,则使用_ 忽略即可,_* 表示所有
case Bundle(_, _, art3 @ Book(_, _), rest3) => (art3, rest3)
}
println("res3=" + res3)
//案例的完成
println("price=" + price(sale)) // 120
}
def price(it:Item): Double = {
it match {
case Book(_,p) => p
case Bundle(_,disc,its @ _*) => its.map(price).sum - disc
}
}
}
//设计样例类
abstract sealed class Item // 项
case class Book(description: String, price: Double) extends Item
case class Food(description: String, price: Double) extends Item
//Bundle 捆 , discount: Double 折扣 , item: Item* ,
case class Bundle(description: String, discount: Double, item: Item*) extends Item