19 scala的模式匹配

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

おすすめ

転載: blog.csdn.net/u014644167/article/details/113100762