Scala-模式匹配

模式匹配

简介

  • 类似于java中switch

  • 当数据满足某一个分支时,执行完毕后,就直接跳出

  • case分支类似于default语言, 分支匹配其实就是顺序匹配

  • 如果数据没有匹配任何规则,会发生错误

    // val age = 20
    //
    // age match {
    // //case _ => println("other")
    // case 10 => println("age = 10")
    // case 30 => println("age = 30")
    // }
     var a: Int = 10
     var b: Int = 20
     var operator: Char = '+'
     var result = operator match {
     case '+' => a + b
     case '-' => a - b
     case '*' => a * b
     case '/' => a / b
     case _ => "illegal"
     }
    

匹配规则

匹配常量

def describe(x: Any) = x match {
 case 5 => "Int five"
 case "hello" => "String hello"
 case true => "Boolean true"
 case '+' => "Char +"
}

匹配类型

  • 类型前增加变量名称,这个变量就是将数据转换成指定类型的变量
  • 如果想要使用下划线代表的数据,可以给下划线起名来使用
def describe(x: Any) = x match {
 case i : Int => i + 10
 case s : String => "String hello"
 case m: List[_] => "List"
 case c: Array[Int] => "Array[Int]"
 case someThing => "something else " + someThing
}
  • scala中类型匹配时,是不考虑泛型的,但是Array类型是特殊的。

    • 类型匹配注意

      Array[Int], 这里的Int不是真正的泛型

      java中的写法 => String[]
      scala中的写法 => Array[String]

      Array[Int] 是一个整体

      List[Int] 是类型加泛型

      不考虑泛型演示

      case m: List[Int] => "List"
      println(describe(List("1", "2", "3"))) ==> List 
      case m: List[string] => "List"
      println(describe(List(1, 2, 3))) ==> List 
      

匹配数组

 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)
 }
 
 result = 0
 result = 1,0
 result = 以0开头的数组
 result = something else
 result = something else
 result = hello,90

匹配列表

 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)
 }
 
 0
 1,0
 0 ...
 something else
 something else

匹配元组

 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)
 }
 0 ...
 10
 1 1
 something else

匹配对象

通过伴生对象定义unapply方法来进行对象之间的相互匹配

 def main(args: Array[String]): Unit = {
 // TODO - 模式匹配 - 匹配规则
 // 匹配对象
 // apply : Attribute => Object
 val user = getUser()
 
 // unapply : Object => Attribute
 user match {
 case User("zhangsan",40) => println("用户为张三")
 case _ => println("什么也不是")
 }
 }
 class User {
 var name:String = _
 var age:Int = _
 }
 object User {
 // Object => Attribute
 def unapply(user: User): Option[(String, Int)] = {
 Option( (user.name, user.age) )
 }
 // Attribute => Object
 def apply( name : String, age:Int ) = {
 val user = new User()
 user.name = name
 user.age = age
 user
 }
 }
 def getUser() = {
 User("zhangsan", 30)
 }

模式匹配用法

  • 直接取元组value
val (_, name, _) = (1, "zhangsan", 30)
println(name) ==> zhangsan 
  • 直接取map的key
val map = Map(
 ("a", 1), ("b", 2), ("c", 3)
)
for ( (k, 2) <- map ) {
 println( k ) ==> b
}
  • 用模式匹配去替换 ‘_ ‘ 加索引
 val list = List(
 (("河北", "鞋"), 10),
 (("河北", "衣服"), 20),
 (("河北", "电脑"), 15),
 )
 list.map(
 (t) => {
 t
 }
 )
 // 下面的代码中,使用模式匹配需要注意:
 // 1. 匹配数据时,需要使用case关键字
 // 2. case分支可能存在多个,那么需要将map的小括号换成大括号
 val list1 = list.map {
 case ((prv, item), cnt) => {
 (prv, (item, cnt * 2))
 }
 }

样例类

在编译时,会自动生成大量的方法

  1. 样例类会自动实现可序列化接口
  2. 样例类的构造参数直接能够作为属性使用,但是不能修改,如果想要修改,需要将参数使用var声明
  3. 增加和重写了大量的方法
  4. 样例类自动生成伴生对象,而且其中自动声明了apply,unapply
 def main(args: Array[String]): Unit = {
 val user = getUser()
 user.name = "lisi"
 user match {
 case User("zhangsan",40) => println("用户为张三")
 case _ => println("什么也不是")
 }
 }
 case class User(var name:String, age:Int)
 def getUser() = {
 User("zhangsan", 40)
 }

偏函数

以偏概全

  • 全量函数 :函数进行处理时必须对所有的数据进行处理。

     
     val list = List(1,2,3,4)
     // map只支持全量函数操作
     // 1 => 2
     // 2 => Unit
     // 3 => 6
     // 4 => Unit
     val list1 = list.map(
     num => {
     if ( num % 2 != 0 ) {
     num * 2
     }
     }
     )
     println(list1) ==> List(2, (), 6, ())
    
  • 偏函数 : 函数进行处理时只对满足条件的数据进行处理

     // 将该List(1,2,3,4,5,6,"test")中的Int类型的元素加一,并去掉字符串
     val list : List[Any] = List(1,2,3,4,5,6,"test")
     val list1 = list.map {
     case i : Int => { // 只匹配Int类型
     i + 1
     }
     case other => other
     }.filter(_.isInstanceOf[Int])
     println(list1)
     val list : List[Any] = List(1,2,3,4,5,6,"test")
     val list1 = list.collect{
     case i : Int => i + 1
     }
     println(list1)
    
作者:POCOPOCOPOCO原文地址:https://www.cnblogs.com/POCOPOCOPOCO/p/16828062.html

%s 个评论

要回复文章请先登录注册