六, Scala 模式匹配总结
六, 模式匹配
- Scala中的模式匹配类似于Java中的switch语法,但是scala从语法中补充了更多的功能, 所以更加强大;
switch(变量){
case '值1':
执行语句;
break;
case '值2':
执行语句;
break;
default:
执行语句;
break;
}
6.1 基本语法
- 模式匹配语法中, 采用
match
关键字声明, 如: 变量名 match 等同于 switch(变量名) , - 每个
分支采用case关键字
进行声明, 如, case ‘’ => 执行语句 等同于 case ‘’: ; 当需要匹配时,会从第一个case分支开始,匹配成功执行本case逻辑, 不成功就下一个分支;- 注意, 每个case不需要像Java那样使用break语句, Scala自动中断case;
- 每一个case的
=>
后的代码块是作为整体执行, {}可用可不用
- 如果所有的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
}
}
}
【推荐】编程新体验,更懂你的AI,立即体验豆包MarsCode编程助手
【推荐】凌霞软件回馈社区,博客园 & 1Panel & Halo 联合会员上线
【推荐】抖音旗下AI助手豆包,你的智能百科全书,全免费不限次数
【推荐】博客园社区专享云产品让利特惠,阿里云新客6.5折上折
【推荐】轻量又高性能的 SSH 工具 IShell:AI 加持,快人一步
· 一个费力不讨好的项目,让我损失了近一半的绩效!
· 清华大学推出第四讲使用 DeepSeek + DeepResearch 让科研像聊天一样简单!
· 实操Deepseek接入个人知识库
· CSnakes vs Python.NET:高效嵌入与灵活互通的跨语言方案对比
· 易语言 —— 开山篇