六, Scala 模式匹配总结

六, 模式匹配

  • Scala中的模式匹配类似于Java中的switch语法,但是scala从语法中补充了更多的功能, 所以更加强大;
switch(变量){
    case '值1':
        执行语句;
        break;
    case '值2':
        执行语句;
        break;
    default:
        执行语句;
        break;
}

6.1 基本语法

  1. 模式匹配语法中, 采用match关键字声明, 如: 变量名 match 等同于 switch(变量名) ,
  2. 每个分支采用case关键字进行声明, 如, case ‘’ => 执行语句 等同于 case ‘’: ; 当需要匹配时,会从第一个case分支开始,匹配成功执行本case逻辑, 不成功就下一个分支;
    • 注意, 每个case不需要像Java那样使用break语句, Scala自动中断case;
    • 每一个case的=>后的代码块是作为整体执行, {}可用可不用
  3. 如果所有的case都不匹配, 就会执行 case _ 分支, 等同于 default: , 没有默认分支case _会抛出 MatchError;

[举个栗子]

package patternmatchdemo

object Caseexpr {
  def main(args: Array[String]): Unit = {
    /**
     * switch(变量){
     *  case '':
     *            xxx;
     *            break;
     *  case '':
     *            yyy;
     *            break;
     *  default:
     *            zzzz;
     *            break;
     * }
     */
    var oprator: Char = ' '
    val a = 8
    val b = 2
    var res = oprator match {
      case '+' =>
          a + b
      case '-' =>
          a - b
      case '*' =>
          a * b
      case '/' =>
          a / b
      case _ => {
        println("注意上面, _不带任何的引号哦!")
        println("not match any operator")
      }

    }
    println(res)
  }
}

6.2 模式守卫

  • 如果想要表达匹配某个范围的数据, 就需要在模式匹配中增加条件守卫
  • 相比于Java 的Switch…Case只能匹配值, 使用Scala的模式守卫可以匹配某个范围的数据, 非常的仁性;
package patternmatchdemo

import scala.io.StdIn

object PatternGuardDemo {
  def main(args: Array[String]): Unit = {
    //模式守卫
    // 让我们来匹配奇数, 偶数
    //通过键盘输入一个数, 让模式守卫来判断
   while(true){
     println("请输入一个偶数或奇数: ")
     val num = StdIn.readInt()

     val res: Any = num match {
       case i: Int if i % 2 == 0 => "您输入的是偶数"
       case j: Int if j % 2 != 0 => "您输入的是奇数"
       case _ => "输入格式错误, 请输出数字"
     }
     println(res)
   }
  }
}

6.2 模式匹配类型

6.2.1 匹配常量

  • Scala中, 模式匹配可以匹配所有的字面量, 包括字符串, 字符, 数字, 布尔值等等
  • 太特么👍
package patternmatchdemo

object TestMatchVal {
  def main(args: Array[String]): Unit = {
    println(defineVal(true))
  }

  def defineVal(x: Any) = {
    x match {
      case 6 => "number 6"
      case "hello" => "String hello"
      case i if i == false || i == true => "Boolean value"
      case 'a' => "char a"
      case _ => "Unkonw Character"
    }
  }
}

6.2.2 匹配类型

  • Scala 进行一个变量或常量的数据类型判断时, 可以使用isInstanceOf[T], 和asInstanceOf[T], 也可以直接用模式匹配实现同样的功能, 是不是碉堡啦?!
  • 你问我怎么使用? 直接在case后定义 X: 数据类型 就行啦!
object TestMatchClass {
    def describe(x: Any) = x match {
        case i: Int => "Int"
        case s: String => "String hello"
        case m: List[_] => "List"
        case c: Array[Int] => "Array[Int]"
        case someThing => "something else " + someThing
}
    def main(args: Array[String]): Unit = {
        //泛型擦除
        println(describe(List(1, 2, 3, 4, 5)))
        //数组例外,可保留泛型
        println(describe(Array(1, 2, 3, 4, 5, 6)))
        println(describe(Array("abc")))
    }
}

6.2.3 匹配数组

  • Scala模式匹配可以对集合进行精确的匹配, 例如匹配只有两个元素且第一个元素为0的数组
package patternmatchdemo

object ArrayPartternMatchDemo {

  def main(args: Array[String]): Unit = {
    for (arr <- Array(Array(0), Array(1, 0), Array(0, 1, 0),
      Array(1, 1, 0), Array(1, 1, 0, 1), Array("hello", 90))) { // 对一个数组集合进行遍历
      val result = arr match {
        case Array(0) => "0" //匹配 Array(0) 这个数组
        //模糊匹配
        case Array(x, y) => x + "," + y //匹配有两个元素的数组,然后将将元素值赋给对应的 x,y
        case Array(0, _*) => "以 0 开头的数组" //匹配以 0 开头和数组
        case _ => "something else"
      }
      println("result = " + result)
    }
  }

}

6.2.4 匹配列表

  • Scala模式匹配列表,在于可以模糊匹配列表中的元素;

第一种方式

object TestMatchList {
  def main(args: Array[String]): Unit = {
    //list 是一个存放 List 集合的数组
    for (list <- Array(List(0), List(1, 0), List(0, 0, 0), List(1,
      0, 0), List(88))) {
      val result = list match {
        
        case List(0) => "0" //匹配 List(0)
        case List(x, y) => x + "," + y //匹配有两个元素的 List
        case List(0, _*) => "0 ..."
        case _ => "something else"
      }
      println(result)
    }
  }
}

第二种方式
first:: second:: rest
第一个元素:: 第二个元素:: 剩下的所有元素

object TestMatchList {
  def main(args: Array[String]): Unit = {
    val list: List[Int] = List(1, 2, 5, 6, 7)
    list match {
      case first :: second :: rest => println(first + "-" +
        second + "-" + rest)
      case _ => println("something else")
    }
  }
}

6.2.5 匹配元组

  • 下面给出匹配元组的代码示例。注意,元组不等同于列表或者数组,这里不能使用 _* 符号表示 "不确定的元素数量 ",因为每一个元组应当是明确的 TupleX 类型。
object TestMatchTuple {
        def main(args: Array[String]): Unit = {
            //对一个元组集合进行遍历
            for (tuple <- Array((0, 1), (1, 0), (1, 1), (1, 0, 2))) {
            
            val result = tuple match {
            
                case (0, _) => "0 ..." //是第一个元素是 0 的元组
                case (y, 0) => "" + y + "0" // 匹配后一个元素是 0的对偶元组
                case (a, b) => "" + a + " " + b
                case _ => "something else" //默认
        }
            println(result)
        }
    }
}

扩展案例
通过模式匹配, 可以很方便的定义元组, 遍历元组

package chapter08

object Test03_MatchTupleExtend {
  def main(args: Array[String]): Unit = {
    // 1. 在变量声明时匹配
    val (x, y) = (10, "hello")
    println(s"x: $x, y: $y")

    val List(first, second, _*) = List(23, 15, 9, 78)
    println(s"first: $first, second: $second")

    val fir :: sec :: rest = List(23, 15 , 9, 78)
    println(s"first: $fir, second: $sec, rest: $rest")

    println("=====================")

    // 2. for推导式中进行模式匹配
    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 13))

    // 2.1 原本的遍历方式
    for (elem <- list){
      println(elem._1 + " " + elem._2)
    }

    // 2.2 将List的元素直接定义为元组,对变量赋值
    for ((word, count) <- list ){
      println(word + ": " + count)
    }

    println("-----------------------")
    // 2.3 可以不考虑某个位置的变量,只遍历key或者value
    for ((word, _) <- list)
      println(word)

    println("-----------------------")

    // 2.4 可以指定某个位置的值必须是多少
    for (("a", count) <- list){
      println(count)
    }
  }
}

再来点例子:

package patternmatchdemo

object ListPatternMatchDemo {

    def main(args: Array[String]): Unit = {
      //特殊的模式匹配 1 打印元组第一个元素
      for (elem <- Array(("a", 1), ("b", 2), ("c", 3))) {
        println(elem._1)
      }
      for ((word,count) <- Array(("a", 1), ("b", 2), ("c", 3))) {
        println(word)
      }
      for ((word,_) <- Array(("a", 1), ("b", 2), ("c", 3))) {
        println(word)
      }
      for (("a",count) <- Array(("a", 1), ("b", 2), ("c", 3))) {
        println(count)
      }
      println("--------------")
      
      //特殊的模式匹配 2 给元组元素命名
      var (id,name,age): (Int, String, Int) = (100, "zs", 20)
      println((id,name,age))
      println("--------------")
      
      
      //特殊的模式匹配 3 遍历集合中的元组,给 count * 2
      var list: List[(String, Int)] = List(("a", 1), ("b", 2), ("c", 3))
      //println(list.map(t => (t._1, t._2 * 2)))
      println(
        list.map{
          case (word,count)=>(word,count*2)
        }
      )
      var list1 = List(("a", ("a", 1)), ("b", ("b", 2)), ("c", ("c", 3)))
      println(
        list1.map{
          case (groupkey,(word,count))=>(word,count*2)
        }
      )
    }
}

除此之外,利用模式匹配我们可以轻松地实现元素交换:

ints match {
  case Array(0) => Array(1,2,3)
  case Array(x,y) => Array(y,x)
  case Array(x,y,z) => Array(x,z,y)
  case _ if ints.length>5 => Array(ints(0),ints(1),ints(2))
  case _ =>Array(0)
}

6.2.6 匹配对象及样例类 _重要!!

参看此文

6.3 变量声明中的模式匹配

object TestMatchVariable {
  def main(args: Array[String]): Unit = {
    val (x, y) = (1, 2)
    println(s"x=$x,y=$y")
    val Array(first, second, _*) = Array(1, 7, 2, 9)
   
    println(s"first=$first,second=$second")
   
    val Person(name, age) = Person1("zhangsan", 16)
    println(s"name=$name,age=$age")
  }
}

6.4 for 表达式中的模式匹配

object TestMatchFor {
  def main(args: Array[String]): Unit = {
    val map = Map("A" -> 1, "B" -> 0, "C" -> 3)
    for ((k, v) <- map) { //直接将 map 中的 k-v 遍历出来
      println(k + " -> " + v) //3 个
    }
    println("----------------------")
    //遍历 value=0 的 k-v ,如果 v 不是 0,过滤
    for ((k, 0) <- map) {
      println(k + " --> " + 0) // B->0
    }
    println("----------------------")
    //if v == 0 是一个过滤的条件
    for ((k, v) <- map if v >= 1) {
      println(k + " ---> " + v) // A->1 和 c->33
    }
  }
}

6.5 偏函数中的模式匹配(了解)(待补充)

posted @   青松城  阅读(111)  评论(0编辑  收藏  举报
相关博文:
阅读排行:
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 易语言 —— 开山篇
点击右上角即可分享
微信分享提示