zoukankan      html  css  js  c++  java
  • scala(四) 模式匹配

    模式匹配

    TODO - 模式匹配 - 匹配规则

      1.类似于java中switch
      2.当数据满足某一个分支时,执行完毕后,就直接跳出
      3.case _ 分支类似于default语言, 分支匹配其实就是顺序匹配
      4.如果数据没有匹配任何规则,会发生错误
      模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,
      如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case _分支,类似于Java中default语句。如果不存在case _分支,那么会发生错误。
    

    1 匹配类型

    类型前增加变量名称,这个变量就是将数据转换成指定类型的变量

    如果想要使用下划线代表的数据,可以给下划线起名来使用(比如 somthing 代替_)

    scala中类型匹配时,是不考虑泛型的,但是Array类型是特殊的。(比如List[_]匹配的list集合无论里面的类型是多少)

    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
            }
    
            // Array[Int], 这里的Int不是真正的泛型
            // java  => String[]
            // scala => Array[String]
            println(describe(List("1", "2", "3")))
    

    2 匹配数组

    判定给定的数组的规则

    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)
    }
    

    3 匹配列表

    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)
    }
     val list: List[Int] = List(1, 2, 5, 6, 7)
    
    list match {
        case first :: second :: rest => println(first + "-" + second + "-" + rest)
        case _ => println("something else")
    }
    
    ::对于这个符号就是追加的意思  上述就是能否分成三部分  1-2-List(5, 6, 7)
    
    对于 val list: List[Int] = List(1)
    println(list.head)    //1
    println(list1.tail)  //list()
    //1::Nil
    println(list1.init) //list() 
    println(list1.last)//1
    //List().append(1)
    

    4 匹配元组

    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)
    }
    
    val map = Map(
               ("a", 1), ("b", 2), ("c", 3)
           )
    
           for ( (k, 2) <- map ) {
                println( k )
            }
    
          for((k,v)<- map){
          println(k+"="+v)
    }
    

    1.匹配数据时,需要使用case关键字

    2.case分支可能存在多个,那么需要将map的小括号换成大括号

    //需求 :   (("河北", "鞋"), 10) =>(河北,(鞋,10))
      val list = List(
                (("河北", "鞋"), 10),
                (("河北", "衣服"), 20),
                (("河北", "电脑"), 15),
            )
    
        val tuples: List[(String, (String, Int))] = list.map(
          (t) => {     //这个t外面的括号代表的是参数列表的括号
            ((t._1._1), (t._1._2, t._2))
          }
        )
        println(tuples)
     val list1 = list.map {
                case ((prv, item), cnt) => {
                    (prv, (item, cnt * 2))
                }
            }
           println(list1)
    

    5 匹配对象

    拿到对象:apply : Attribute => Object比对时需要 unapply : Object => Attribute

     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)
        }
    }
    

    5 样例类

    对匹配对象的一种简化,省去了大量的代码,如果在类的前面的增加case关键字,这个类专门用于模式匹配,称之为样例类

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

    1. 样例类会自动实现可序列化接口

    2. 样例类的构造参数直接能够作为属性使用,但是不能修改,如果想要修改,需要将参数使用var声明

    3. 增加和重写了大量的方法 如apply、unapply、toString、equals、hashCode和copy。

    4. 样例类自动生成伴生对象,而且其中自动声明了apply,unapply

    5. 构造器中的每一个参数都成为val,除非它被显式地声明为var(不建议这样做)

    def main(args: Array[String]): Unit = {
    
            // TODO - 模式匹配 - 匹配规则
    
            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)
        }
    

    6 偏函数

    所谓的偏函数,其实就是对集合中符合条件的数据进行处理的函数

    全量函数 :函数进行处理时必须对所有的数据进行处理。map只支持全量函数操作 flatmap

    def main(args: Array[String]): Unit = {
    
        val list = List(1,2,3,4)     //map只支持全量函数操作 即使不满足也要处理 不满足就是没有值 UNIT 
        val list1: List[AnyVal] = list.map(
          num => {
            if (num % 2 != 0) {
              num * 2
            }
          }
        )
        println(list1)
      }
    List(2, (), 6, ())
    
    需求:将该List(1,2,3,4,5,6,"test")中的Int类型的元素加一,并去掉字符串
    1.不使用偏函数
    val newlist : List[Any] = list.filter(_.isInstanceOf[Int])
    val newlist1 = newlist.map(_.asInstanceOf[Int] + 1)
    println(newlist1)
    2.模式匹配
    val list1 = list.map {
                case i : Int => {
                    i + 1
                }
                case other => other
            }.filter(_.isInstanceOf[Int])
    
            println(list1)
    3.偏函数
    def main(args: Array[String]): Unit = {
    
            // TODO - 模式匹配 - 偏函数
    
            val list : List[Any] = List(1,2,3,4,5,6,"test")
    
            val list1 = list.collect{
                case i : Int => i + 1
            }
            println(list1)
    
        }
    
    
  • 相关阅读:
    认识ASP.NET 中的 AppDomain
    试验总结1 改变递归函数中的执行内容
    试验总结2 break与continue
    开篇的话
    01复杂度3 二分查找
    02线性结构2 一元多项式的乘法与加法运算
    01复杂度2 Maximum Subsequence Sum
    02线性结构4 Pop Sequence
    01复杂度1 最大子列和问题
    02线性结构1 两个有序链表序列的合并
  • 原文地址:https://www.cnblogs.com/xiao-bu/p/14810496.html
Copyright © 2011-2022 走看看