Scala-模式匹配

news2024/12/28 21:04:52

基本语法

模式守卫

匹配类型

匹配对象 


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

基本语法

模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需 要匹配时,会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹 配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _分支, 类似于 Java 中 default 语句。

//基本语法
    val x : Int = 10
    val y : String = x match {
      case 1 => "一"
      case 2 => "二"
      case 3 => "三"
      case 4 => "四"
      case _ => "其他" //未满足以上则返回默认值
    }
    println(y)

    //用法示例: 用模式匹配实现简单二元运算
    val a = 25
    val b = 20

    def matchTow(op : Char) = op match {
      case '+' => a+b
      case '-' => a-b
      case '*' => a*b
      case '/' => a/b
      case _ => -1
    }
    println(matchTow('+'))
  1. 如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句, 若此时没有 case _ 分支,那么会抛出 MatchError
  2. 每个 case 中,不需要使用 break 语句,自动中断 case。
  3. match case 语句可以匹配任何类型,而不只是字面量。
  4. => 后面的代码块,直到下一个 case 语句之前的代码是作为一个整体执行,可以 使用{}括起来,也可以不括。 

模式守卫

如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。

//模式守卫
      //求整数绝对值
    def abs (a :Int): Int ={
      a match {
        case i if i >= 0 => i
        case i if i < 0 => -i
      }
    }
    println(abs(-5))

匹配类型

需要进行类型判断时,可以使用前文所学的 isInstanceOf[T]和 asInstanceOf[T],也可使 用模式匹配实现同样的功能。

匹配常量

 //匹配常量
    def des(x : Any): String ={
      x match {
        case 1 => "one"
        case "hello" => "hello scala"
        case true => "yes"
        case '=' => "=="
        case _ => "null"
      }
    }
    println(des("hello"))
    println(des(0.3))

匹配类型

//匹配类型
    def des(a: Any): String = {
      a match {
        case i: Int => "Int "+i
        case i: String => "String "+i
        case i: List[String] => "List "+i
        case i: Array[Int] => "Array "+i.mkString(" ")
        case i => "null" +a
      }
    }
    println( des("s"))

匹配数组

//匹配数组
    for (i <- List(Array(0),Array(1,0),Array(0,1,0),Array(1,0,1))){
      val res = i match {
        case Array(0) => "0"
        case Array(1,0) => "Array(1,0)"
        case Array(0,1,0) => "Array(0,1,0)"
        case Array(x,y) => "Array:" +x +"  "+y //匹配数组中只有两个元素的数组
        case Array(0, _*) => "以0开头的数组"
        case Array(x,0,y) => "0在数组第二位"
        case _ => "没有"
      }
      println(res)
    }

匹配列表

//匹配列表
    val list = List(1,2,3,4,5)
    list match {
      case first :: second :: rest => println(s"f:$first,s:$second,r:$rest") //匹配元素3个或以上的数组
      case _=> println("null")
    }

匹配元组

 //匹配元组
    for (tu <- List((1,1),(0,2),(1,5,4),(1,0,1),("hello",0.1))){
      val res = tu match {
        case (a,b) => "二元组:"+s"($a,$b)"
        case (0,_) => "第一个元素是0的二元组"
        case (a,1,_) => "1为第二个元素的元组"
        case _ => "null"
      }
      println(res)
    }

    //在变量声明时匹配
    val (x,y) =(1,2)
    println(x+" "+y)
    val List(f ,s ,_*) = List(1,2,3,4)
    println(f+" "+s+" ")
    val a :: b :: c = List(1,2,3,4,5,6)
    println(a,b,c)

 for推导式模式匹配

// for推导式模式匹配
    val list : List[(String,Int)] = List(("a",1),("b",2))

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

    //不考虑某个位置的变量,只遍历key或value
    for ((word,_) <- list){
      println(word)
    }

      //可以指定某个位置的值是多少
    for (("a",count) <- list){ //只输出key为a的元组的value
      println(count)
    }

匹配对象 

基本语法

class User(val name: String, val age: Int)
object test {
  def main(args: Array[String]): Unit = {
    val s = new S1("name",20)
    //实例内容进行匹配
    val rs = s match {
      case S1("name",20) => "yes"
      case _ => "no"
    }
    println(rs)
  }
}
//定义类
class S1(val name :String,val age : Int)
//定义伴生对象
object S1 {
  def apply(name: String, age: Int): S1 = new S1(name, age)
  //必须实现unapply方法 ,用来对对象属性进行拆包
  def unapply(s1: S1): Option[(String, Int)] = {
    if (s1 == null){
      None
    }else {
      Some((s1.name,s1.age))
    }
  }
}
  1. val user = User("zhangsan",11),该语句在执行时,实际调用的是 User 伴生对象中的 apply 方法,因此不用 new 关键字就能构造出相应的对象。
  2. 当将 User("zhangsan", 11)写在 case 后时[case User("zhangsan", 11) => "yes"],会默 认调用 unapply 方法(对象提取器),user 作为 unapply 方法的参数,unapply 方法 将 user 对象的 name 和 age 属性提取出来,与 User("zhangsan", 11)中的属性值进行 匹配
  3. case 中对象的 unapply 方法(提取器)返回 Some,且所有属性均一致,才算匹配成功, 属性不一致,或返回 None,则匹配失败。
  4.  若只提取对象的一个属性,则提取器为 unapply(obj:Obj):Option[T]
  5. 若提取对象的多个属性,则提取器为 unapply(obj:Obj):Option[(T1,T2,T3…)]
  6. 若提取对象的可变个属性,则提取器为 unapplySeq(obj:Obj):Option[Seq[T]

 样例类

语法:

case class Person (name: String, age: Int)
  1. 样例类仍然是类,和普通类相比,只是其自动生成了伴生对象,并且伴生对象中 自动提供了一些常用的方法,如 apply、unapply、toString、equals、hashCode 和 copy。 
  2. 样例类是为模式匹配而优化的类,因为其默认提供了 unapply 方法,因此,样例 类可以直接使用模式匹配,而无需自己实现 unapply 方法。
  3. 构造器中的每一个参数都成为 val,除非它被显式地声明为 var(不建议这样做) 
object mc {
  def main(args: Array[String]): Unit = {
    val s = S2("name",20)
    //实例内容进行匹配
    val rs = s match {
      case S2("name",20) => "yes"
      case _ => "no"
    }
    println(rs)
  }
}
//定义样例类
case class S2(name: String,age : Int )

 偏函数匹配 

偏函数定义:

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

原理:

上述代码会被 scala 编译器翻译成以下代码,与普通函数相比,只是多了一个用于参数 检查的函数——isDefinedAt,其返回值类型为 Boolean。 

val second = new PartialFunction[List[Int], Option[Int]] {
 //检查输入参数是否合格
 override def isDefinedAt(list: List[Int]): Boolean = list match 
{
 case x :: y :: _ => true
 case _ => false
 }
 //执行函数逻辑
 override def apply(list: List[Int]): Option[Int] = list match 
{
 case x :: y :: _ => Some(y)
 }
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/380402.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

C++学习笔记-内存空间

考虑这样一种情况&#xff0c;当我们使用相同的名称&#xff0c;叫Zara的两个人在同一个班级。我们需要明确区分它们将不得不使用一些额外的信息&#xff0c;如他们的名字&#xff0c;如他们生活在不同的区域或母亲或父亲的名字等等。 同样的情况也出现在C应用程序中。例如&am…

Ubuntu 18.04.6 LTS 服务版安装参考

文章目录安装环境安装过程等待安装进行设置语言选择更新设置键盘样式设置IP地址配置代理配置 Ubuntu 存档镜像自定义存储配置设置账号配置 SSH安装软件包等待安装完成重启后验证安装后的基础优化重置 root 密码放开 root 远程登陆网卡信息变更修改ubuntu-18.04.6-live-server-a…

怎么用白光干涉仪的拼接测量功能

白光干涉仪的基本原理是通过不同的光学元件形成参考光路和探测光路&#xff0c;是利用干涉原理测量光程差&#xff0c;从而确定相关物理量的光学仪器。结合精密Z向扫描模块、3D 建模算法等&#xff0c;可以对器件表面进行非接触式扫描并建立表面3D图像&#xff0c;然后通过一体…

普通指针扫盲

一、什么是指针 C语言里&#xff0c;变量存放在内存中&#xff0c;而内存其实就是一组有序字节组成的数组&#xff0c;每个字节有唯一的内存地址。 CPU 通过内存寻址对存储在内存中的某个指定数据对象的地址进行定位。这里&#xff0c;数据对象是指存储在内存 中的一个指定数据…

【项目精选】病历管理系统设计与实现(源码+视频)

点击下载源码 企业财务管理系统主要用于电子病历来提高医院各项工作的效率和质量&#xff0c;促进医学科研、教学&#xff1b;减轻各类事务性工作的劳动强度&#xff0c;使他们腾出更多的精力和时间来服务于病人。本系统结构如下&#xff1a; 电子病例系统&#xff1a; 病人登…

通过知识库深度了解用户的心理

自助服务知识库的价值是毋庸置疑的&#xff0c;如果执行得当&#xff0c;可以帮助减少客户服务团队的工作量&#xff0c;仅仅编写内容和发布是不够的&#xff0c;需要知道知识库对客户来说是否有用&#xff0c;需要了解客户获得的反馈&#xff0c;如果你正确的使用知识库软件&a…

哪款蓝牙耳机打电话好用?打电话音质好的蓝牙耳机

现在几乎是人人离不开耳机的时代。在快节奏的生活和充满嘈杂声音的世界中&#xff0c;戴着耳机听歌&#xff0c;是每个人生活中最不可或缺的一段自由、放松的时光&#xff0c;下面小编就来分享几款通话音质好的蓝牙耳机。 一、南卡小音舱蓝牙耳机 动圈单元&#xff1a;13.3mm…

伯恩光学再成被执行人:多次因劳动纠纷被起诉,曾冲刺港交所上市

近日&#xff0c;贝多财经从天眼查APP了解到&#xff0c;伯恩光学&#xff08;深圳&#xff09;有限公司&#xff08;下称“伯恩光学”&#xff09;因《伯恩光学&#xff08;深圳&#xff09;有限公司与温*燕劳动合同纠纷的案件》一事&#xff0c;被广东省深圳市龙岗区人民法院…

服务端开发之Java备战秋招面试篇6-Java各种并发锁

努力了那么多年,回头一望,几乎全是漫长的挫折和煎熬。对于大多数人的一生来说,顺风顺水只是偶尔,挫折、不堪、焦虑和迷茫才是主旋律。我们登上并非我们所选择的舞台,演出并非我们所选择的剧本。继续加油吧&#xff01; 目录 1、Java中主流锁分类体系介绍 2、乐观锁CAS原理刨…

wordpress 占用内容过高的解决方案

WordPress占用内存过高可能由多种因素引起&#xff0c;以下是一些可能的原因和解决方法&#xff1a; 主题和插件&#xff1a; WordPress的主题和插件是最常见的内存占用原因。确保使用的主题和插件是最新版本&#xff0c;并且只使用必需的插件。禁用不需要的插件&#xff0c;并…

【Linux】文件时间-ACM

文章目录文件时间-acmAccessChangeModify文件时间-acm 我们可以使用stat 文件名的方式查看对应的文件的时间信息 Access 表示文件最近一次被访问的时间 文件的访问 实际也就是文件的读取 实际操作中,文件的Access时间可能没有变化,这是因为在新的Linux内核中,Access时间不…

JavaScript 闭包的理解

1、概念 一个函数对周围状态的引用捆绑在一起&#xff0c;内层函数中访问到其外层函数的作用域 2、简单理解 闭包 内层函数 引用的外层函数变量 简单代码示例&#xff1a; function outer(){let i 1; // 被内层函数引用的变量function fn(){ // 内层函数console.log(i…

用javascript分类刷leetcode5.二分查找(图文视频讲解)

二分搜索 时间复杂度O(logn) 步骤&#xff1a; 从数组中间的元素开始&#xff0c;如果中间的元素正好是目标值&#xff0c;搜索结束如果目标值大于或小于中间的元素&#xff0c;则在大于或小于中间的元素的那一半继续搜索 代码模版 //二分查找伪代码模版 while (left <…

3.1 模拟栈+表达式求值+模拟队列+单调栈

模拟栈 题目链接 栈的数组模拟非常简单&#xff0c;不详细描述 设置一个指针指向栈顶第一个元素即可 STL中stack实现已经更新在STL_Stack #include<iostream> #include<string>using namespace std;const int N1e51; int m; string s; int stack[N]; int p;//指针…

Cartesi 2023 年 2 月回顾

2023年2月28日&#xff0c;通过ETH Denver和Cartesi的在线全球黑客马拉松一起开启黑客马拉松赛季!ETH Denver 正在热火朝天的进行着&#xff0c;我们正在为3月25日开始的首个全球在线黑客马拉松做准备。但这并不是本月发生的所有事情。我们在继续扩展和发展在全世界各地的社区&…

【软件测试】接口测试和接口性能测试,资深测试老鸟的总结......

目录&#xff1a;导读前言一、Python编程入门到精通二、接口自动化项目实战三、Web自动化项目实战四、App自动化项目实战五、一线大厂简历六、测试开发DevOps体系七、常用自动化测试工具八、JMeter性能测试九、总结&#xff08;尾部小惊喜&#xff09;前言 只会独立使用工具&a…

程序员必备!最值得收藏的宝藏网站大盘点

做为程序员&#xff0c;没有收藏点宝藏网站都说不过去。 除了常见的大家熟知的知乎、谷歌、b站、CSDN、掘金等&#xff0c;今天将介绍一些其他更加实用的宝藏网站&#xff0c;程序员小伙伴们可以按需收藏哦&#xff5e; 1.菜鸟教程&#xff1a;https://www.runoob.com/ 国内…

大数据处理技术导论(6) | Datawhale组队学习46期

文章目录1. hive 概述2. hive 与传统关系型数据库的对比3. hive 数据类型4. hive 数据模型5. hive 实战5.1 创建表5.2 修改表5.3 清空表、删除表5.4 其他命令项目地址 https://github.com/datawhalechina/juicy-bigdata&#xff0c;感谢项目团队的付出。本次主要学习 hive 相关…

web,h5海康视频接入监控视频流记录三(后台node取流)

前端vue&#xff0c;接入ws视频播放 云台控制 &#xff0c;回放预览&#xff0c;都是需要调对应的海康接口。相当于&#xff0c;点击时&#xff0c;请求后台写好的接口&#xff0c;接口再去请求海康的接口 调用云台控制是&#xff0c;操作一次&#xff0c;不会自己停止&#x…

元宇宙如何在未来5年影响你的业务

自新冠疫情暴发以来&#xff0c;虽然数字经济的和实体经济受到了严重的冲击和影响&#xff0c;但这也加速了元宇宙在全球的发展。区块链、数字资产和非同质化代币&#xff08;NFTs&#xff09;的兴起进一步推动了世界对元宇宙的需求。元宇宙被定义为用户可以在其中进行互动的虚…