Scala基础8——第8章:模式匹配

第8章 模式匹配

​ Scala中的模式匹配,类似于Java中的switch语法

8.1 基本语法

​ 模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明。

​ match语法中没有break语句

​ case _ 默认值, 如果没有case _ 则会抛出异常MatchError。

​ 注:默认值并不需要一定是case _ ,下划线只是一个通配符,下划线可以是任意的变量名,如case acase abccase _

object Test01{
    def main(args:Array[String]):Unit={
        
        // 1 基本语法
        val x:Int = 2
        val y:String = x match {
            case 1 => "one"
            case 2 => "two"
            case 3 => "three"
            case _ => "other" // 默认值
        }
        println(y)
        
        // 2 示例:用模式匹配实现简单的二元运算
        val a = 25
        val b = 13
        
        def matchDualOp(op : Char):Int = op match {
            case '+' => a + b
            case '-' => a - b
            case '*' => a * b
            case '/' => a / b
            case '%' => a % b
            case _ => -1
        }
        println(matchDualOp('+'))
        println(matchDualOp('-'))
        println(matchDualOp('*'))
    }
}


8.2 模式守卫

模式守卫, 通过if来进行判断

object Test01{
    def main(args:Array[String]):Unit={
        
        // 模式守卫, 通过if来进行判断
        // 求绝对值
        def abs(num:Int):Int={
            num match{
                case i if i >=0 => i
                case i if i <0  => -i
            }
        }     
    }
}

8.3 模式匹配类型

​ 模式匹配可以匹配所有的字面量,包括字符串,数组,数字,布尔值等

8.3.1 匹配常量

object Test02{
    def main(args:Array[String]):Unit={
        // 1 匹配常量
        def describeConst(x : Any):String= x match{
            case 1 => "Num One"
            case "hello" => "string hello"
            case true => "true"
            case '+' => "Char +"
            case _ => "默认值" // 没有case _ 则会抛出异常MatchError
        }
        
    }
}

8.3.2 匹配类型

泛型擦除,也就是 List[String],JVM只会判断他是一个List,并不会判断他的泛型。 如List[Int],List[Double]都会认为是List

Array类型没有泛型擦除,所以Array可以判断泛型

object Test02{
    def main(args:Array[String]):Unit={
        
        
        def describeType(x : Any):String = x match{
            case i:Int => "Int"+i //匹配Int类型
            case s:String => "String"+s //
            case list:List[String] => "List"+list//List的泛型是没有用的,泛型擦除
            case array:Array[Int] => "Array[Int]"+array.mkString(",") // array的泛型有用
            case a => "默认值" + a //默认值并不需要用_,_只是一个通配符
        }
        
        println(describeType(List(1,2,3,4))) // List
    }
}

8.3.3 匹配数组

匹配数组

object Test02{
    def main(args:Array[String]):Unit={
        
        
        for( arr <- List( Array(0) , Array(1,0) , Array(1,0,1), Array("hello",20) ) ){
            val result = arr match{
                case Array(0) => "一个元素,且只能为0" 
                case Array(1,0) => "Array(1,0)"
                case Array(x,y) => "匹配只有两个元素的Array"+ x + y
                case Array(0 , _*) => "第一个必须是0,剩下的不限"
                case Array(x,1,z) => "三个元素,第二个元素必须是1"
                case _ => "默认值"
                
            }
            println(result)
        }
        
        
    }
}

8.3.4 匹配List

匹配列表

object Test02{
    def main(args:Array[String]):Unit={
        // 方式1
        for (list <-List(List(0),List(1,0),List(1,0,1)){
        val result = list match{
            case List(0) => "只有一个元素,只能为0"
            case List(x,y) => "两个元素,分别为"+x+y
            case List(0, _*) => "以0开始"
            case List(a) => "只有一个元素"+a
            case _ => "默认值"
        }
            
        // 方式2
        val list = List(1,2,3,4)
        list match{
            case first :: second :: rest => println(s"$first , $second , $rest") 
            case _ => println("默认值")
        }
        // 输出结果
        // 1 , 2 , List(3,4)
        
    }
      
}

8.3.5 匹配元组

object Test02{
    def main(args:Array[String]):Unit={
        
        
        for (tuple <- List ( (0,1) , (0,2) , (0,1,0), (1,"hello",1) )){
            val result = tuple match{
                case (a , b) => "二元组,分别是"+"("+a+","+b+")"
                case (0 , _) => "第一个元素是0,并且是二元组"
                case (a,b,0) => "三元组,最后一个是0"
                case (x,y,z) => "三元组,分别是"+x+y+z   
            }
        }
       
    }
}

元组匹配的扩展

object Test03{
    def main(args:Array[String]):Unit={
        
        // 1 在变量声明时匹配
        val (x,y) = (10 , "hello")
        println(s" $x , $y ")
        
        val List(first, second , _*) = List(23,15,9,78)
        println(first + " " + second)
        
        
        fir :: sec :: rest = List(12,34,23,75)
        println(fir + " " + sec + " " + rest)
        // 12 34 List(23,75)
        // fir表示12 , sec表示34 , rest表示List(23,75)
        
        
        // 2 for推导式中进行模式匹配
        val list:List[(String,Int)] = List(("a",12),("b",35),("c",27))
        
        // 遍历方式1
        for(elem <- list){
            println(elem._1 + " " + elem._2)
        }
        
        // 遍历方式2
        // 将List的元素直接定义为元组,对变量赋值
        for( (word,count) <- list ){
            println(word + " " + count)
        }
        
        // 遍历方式3
        for( (word,_) <- list ){
            println(word)
        }
        
        // 可以指定某个位置的值,必须是多少
        // 元组的第一个数必须是"a"
        for( ("a",count) <- list){
            println(count)
        }
    }
}

8.3.6 匹配对象及样例类

(1)定义类

(2)定义伴生对象,写apply方法和 unapply方法

object Test04{
    def main(args:Array[String]):Unit={
        val student = new Student("alice",18)
        
        // 针对对象实例的内容进行匹配
        val result = student match{
            case Student("alice",18) => "alice,18"
            case _ => "默认值"
        }
    }   
}

// 定义类
class Student(val name:String, val age:Int)

// 定义伴生对象
object Student{
    def apply(name:String,age:Int):student = new Student(name,age)
    // 必须实现一个unapply方法,用来对对象属性进行拆解
    def unapply(student:Student):Option[(String,Int)]={
        if(student== null){
            None
        }else{//匹配规则
            Some((student.name, student.age))
        }
    }
}

样例类

通过case关键字,就可以直接实现伴生对象的apply方法和unapply方法

object Test05{
    def main(args:Array[String]):Unit={
        val student = Student("alice",18)
        
        // 针对对象实例的内容进行匹配
        val result = student match{
            case Student("alice",18) => "alice,18"
            case _ => "默认值"
        }
    }
}

// 定义为样例类,
// 自动生成伴生对象的apply方法和unapply方法
case class Student1(name:String , age:Int)

8.4 偏函数中的模式匹配(了解)

​ 偏函数是函数的一种。

​ 例如该偏函数输入的类型为List[Int],而我们需要的是第一个元素是0的集合,就是通过模式匹配实现的。

偏函数的定义

val second:PartialFunction[List[Int],Option[Int]]={
    case x :: y :: _ => Some(y)
}

偏函数:只处理自己感兴趣的匹配。

所以在代码中需要定义多个偏函数,完成全部功能

object Test06{
    def main(args:Array[String]):Unit={
        val list:List[(String,Int)] = List(("a",12),("b",20) , ("c",27))
        
        // map转换,实现key不变,value2倍
        val newList = list.map(tuple => (tuple._1 , tuple._2 * 2))
        
        // 2 用模式匹配对元组元素赋值,实现功能
        val newList2 = list.map(
        	tuple => {
                tuple match{
                    case (word,count) => (word , count*2)
                }
            }
        )
        
        // 3 省略lambada表达式的写法,进行简化
        // 即偏函数
        val newList3 = list.map(
                case (word,count) => (word, count *2)
        )
        
        println(newList)
        println(newList2)
        println(newList3)
        
    }
}

偏函数的应用

object Test06{
    def main(args:Array[String]):Unit={
        // 偏函数的应用,求绝对值
        // 对输入数据分为不同的情形,正、负、0
        // 对于大于0的部分
        val positiveAbs:PartialFunction[Int,Int] = {
            case x if x > 0 => x
        }
        // 对于小于0的部分
        val negativeAbs:PartialFunction[Int,Int] = {
            case x if x < 0 => x
        }
        val zeroAbs:PartialFunction[Int,Int] = {
            case 0 => 0
        }
        
        // 多个偏函数组成一个完整的函数,然后把x传进去
        def abs(x:Int):Int = (positiveAbs orElse negativeAbs orElse zeroAbs)(x)
        
        println(abs(-67))
        println(abs(68))
        
    }
}
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值