Scala的模式匹配
Scala的模式匹配
Scala 中的模式匹配类似于Java 中的 switch 语法:下面是java中switch代码:
int i = 10
switch (i) {case 10 :System.out.println("10");break;
case 20 :System.out.println("20");break;
default :System.out.println("other number");break;
}
但是 scala 从语法中补充了更多的功能,所以更加强大。
基本语法
模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需要匹配时,会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _分支,类似于 Java 中 default 语句。
object Test_PatternMatchBase {def main(args: Array[String]): Unit = {// 1. 基本定义语法val x: Int = 5val y: String = x match {case 1 => "one"case 2 => "two"case 3 => "three"case _ => "other"}println(y)// 2. 示例:用模式匹配实现简单二元运算val a = 25val b = 13def matchDualOp(op: Char): Int = op match {case '+' => a + bcase '-' => a - bcase '*' => a * bcase '/' => a / bcase '%' => a % bcase _ => -1}println(matchDualOp('+'))println(matchDualOp('/'))println(matchDualOp('\\'))println("=========================")// 3. 模式守卫// 求一个整数的绝对值def abs(num: Int): Int = {num match {case i if i >= 0 => icase i if i < 0 => -i}}println(abs(67))println(abs(0))println(abs(-24))}
}
- 说明
(1) 如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句,若此时没有case _ 分支,那么会抛出MatchError。
(2) 每个case 中,不需要使用break 语句,自动中断case。
(3) match case 语句可以匹配任何类型,而不只是字面量。
(4) => 后面的代码块,直到下一个 case 语句之前的代码是作为一个整体执行,可以使用{}括起来,也可以不括。
在 Scala 中,模式匹配(Pattern matching)是一种强大的特性,用于对数据进行分析和处理。它可以在一个表达式中确定一个值是否匹配了某个模式,并且在匹配成功时执行相应的代码块。模式匹配可以应用于各种类型的对象,包括整数、字符、字符串、列表等。
模式匹配基本使用示例
Scala 的模式匹配语法类似于 switch 语句,但更加强大和灵活。以下是一些基本的模式匹配示例:
val x: Any = 123x match {case i: Int => println("整数:" + i)case s: String => println("字符串:" + s)case d: Double => println("双精度浮点数:" + d)case _ => println("未知类型")
}
在上面的代码中,我们将一个任意类型的值 x 进行了模式匹配。首先,我们使用 case i: Int => 匹配整数类型并将其赋值给变量 i,然后执行 println("整数:" + i) 输出整数。接着,我们使用 case s: String => 匹配字符串类型,并输出对应的信息。最后,我们使用 _ 表示其他所有类型并输出 “未知类型”。
除了基本类型之外,模式匹配还支持对列表、元组等复杂类型进行匹配,例如:
def sum(lst: List[Int]) : Int = lst match {case Nil => 0case x :: tail => x + sum(tail)
}println(sum(List(1, 2, 3))) // 输出 6
在上面的代码中,我们定义了一个 sum 函数用于计算列表中所有整数的和。在函数内部,我们使用模式匹配来处理两种情况:当列表为空时(case Nil => 0),返回 0;否则,我们使用 case x :: tail => 匹配列表的头部元素 x 和剩余元素 tail,并递归地调用 sum(tail) 来计算剩余元素的和,并将其与头部元素 x 相加。
需要注意的是,在模式匹配中,每个匹配分支都必须满足类型一致性和互斥性,以避免出现匹配二义性的情况。
模式守卫
- 说明
如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。 - 代码示例
object TestMatchGuard {
def main(args: Array[String]): Unit = {//求一个整数的绝对值
def abs(x: Int) = x match {
case i: Int if i >= 0 => i
case j: Int if j < 0 => -j
case _ => "type illegal"
}
println(abs(-5))
}
}
模式匹配类型
在 Scala 中,模式匹配非常灵活,可以在各种情况下使用。以下是一些常见的模式匹配运用情况示例:
匹配基本类型和常量值
val x: Any = 123x match {case 0 => println("匹配到 0")case 1 | 2 => println("匹配到 1 或 2")case i: Int if i > 100 => println("匹配到大于 100 的整数")case _ => println("未匹配到")
}
匹配元组
val tuple: (String, Int) = ("Scala", 3)tuple match {case ("Java", _) => println("第一个元素是 Java")case (str, num) if num > 0 => println(s"第一个元素是 $str,第二个元素是正整数")case _ => println("未匹配到")
}
匹配列表List
val list: List[Int] = List(1, 2, 3)list match {case Nil => println("空列表")case head :: tail => println(s"头部元素是 $head,剩余元素是 $tail")
}
匹配类和对象
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
case object UnknownShape extends Shapeval shape: Shape = Circle(3.0)shape match {case Circle(r) => println(s"圆形,半径是 $r")case Rectangle(w, h) => println(s"矩形,宽度是 $w,高度是 $h")case UnknownShape => println("未知形状")
}
使用模式守卫进行更复杂的匹配
val x: Any = List(1, 2, 3)x match {case list: List[_] if list.nonEmpty => println("非空列表")case list: List[_] if list.isEmpty => println("空列表")case str: String if str.length > 10 => println("字符串长度大于 10")case _ => println("未匹配到")
}
匹配数组
在 Scala 中,匹配数组与匹配列表的方式类似。你可以使用模式匹配对数组进行处理。以下是一个示例:
val array: Array[Int] = Array(1, 2, 3)array match {case Array() => println("空数组")case Array(1) => println("单个元素数组")case Array(1, 2, _*) => println("以1和2开头的数组")case Array(_, _, 3) => println("以3结尾的数组")case _ => println("未匹配到")
}
在上面的代码中,我们匹配了不同类型的数组情况。首先,使用 case Array() 匹配空数组;然后,使用 case Array(1) 匹配只包含一个元素的数组;接着,使用 case Array(1, 2, _*) 匹配以 1 和 2 开头的任意长度的数组;最后,使用 case Array(_, _, 3) 匹配以 3 结尾的数组。如果没有匹配到任何情况,就会执行最后一个 case 分支。
需要注意的是,在匹配可变长度的数组时,我们使用了 _* 表示任意长度的数组片段。
变量声明中的模式匹配
在 Scala 中,可以在变量声明中使用模式匹配来提取和赋值变量的值。这种方式被称为模式匹配的变量声明或解构赋值。以下是一个示例:
val tuple: (String, Int) = ("Scala", 3)val (str, num) = tupleprintln(s"字符串:$str")
println(s"整数:$num")
在上面的代码中,我们声明了一个元组 tuple,包含两个元素:一个字符串和一个整数。然后,我们使用模式匹配的方式将元组中的值解构并赋给了两个新的变量 str 和 num。这样,我们就可以通过这两个变量来访问元组中的值。
除了元组,还可以在变量声明中匹配其他数据结构,比如列表、数组等。示例如下:
val list: List[String] = List("Hello", "World")val head :: tail = listprintln(s"头部元素:$head")
println(s"剩余元素:$tail")
在上面的代码中,我们声明了一个列表 list,包含两个字符串元素。然后,使用模式匹配的变量声明方式将列表的头部元素赋给变量 head,剩余元素赋给变量 tail。这样,我们就可以分别访问列表的头部元素和剩余元素。
需要注意的是,模式匹配的变量声明在匹配失败时会抛出 MatchError 异常。为了避免这种情况,请确保变量声明与待解构的数据结构具有相同的结构和类型。
匹配对象及样例类
在 Scala 中,可以使用模式匹配来匹配各种类型的对象,包括普通类和样例类。其中,样例类是一种特殊的类,它专门用于模式匹配,因为编译器会自动生成带有模式匹配相关方法的代码。以下是一个示例:
sealed trait Fruit
case class Apple(color: String) extends Fruit
case class Banana(length: Int) extends Fruit
case object UnknownFruit extends Fruitval fruit: Fruit = Apple("red")fruit match {case Apple("red") => println("红色苹果")case Banana(len) if len > 10 => println("长度大于 10 的香蕉")case UnknownFruit => println("未知水果")case _ => println("其他水果")
}
在上面的代码中,我们定义了一个 Fruit 样例类及两个子类 Apple 和 Banana,还有一个对象 UnknownFruit。然后,我们创建了一个 Apple 对象并将其赋给 fruit 变量。接着,使用 match 关键字来匹配不同类型的 Fruit 对象,分别输出相应的提示信息。
需要注意的是,当匹配样例类时,可以使用模式匹配提取出样例类中的属性值,并对其进行比较。在上面的代码中,使用 case Apple("red") 匹配颜色为红色的苹果。
嵌套模式匹配
当数据结构较为复杂时,可以使用嵌套的模式匹配来逐级解构和匹配。
sealed trait Location
case class City(name: String) extends Location
case class Country(name: String, capital: City) extends Locationdef printCapital(location: Location): Unit = {location match {case Country(_, City(capital)) => println(s"首都是$capital")case _ => println("未知位置")}
}
在上面的代码中,我们定义了一个 Location 类及其两个子类 City 和 Country。Country 类包含一个 City 类的实例作为首都。通过嵌套的模式匹配,我们可以提取和打印出国家的首都。
相关文章:
Scala的模式匹配
Scala的模式匹配 Scala 中的模式匹配类似于Java 中的 switch 语法:下面是java中switch代码: int i 10 switch (i) {case 10 :System.out.println("10");break; case 20 :System.out.println("20");break; default :System.out.pr…...
HttPClient简介及示例:学习如何与Web服务器进行通信
文章目录 前言一、引入依赖二、使用步骤1.创建被调用者2.创建调用者三、结果被调用者服务:调用者服务: 总结 前言 欢迎来到本篇博客,这是一个关于HttPClient的入门案例的指南。🎉 在今天的网络世界中,与服务器进行数据…...
STS4 New 安装Spring Bean Configuration File
背景介绍 在创建spring项目后,如果想想创建spring bean Configuration的时候,发下菜单没有这个选项,需要通过下载Spring Roo插件可满足该操作。 参考案例 参考地址: STS4 New 菜单没有Spring Bean Configuration File选项_SQZHA…...
Java经典面试题(异或运算)
不爱生姜不吃醋⭐️⭐️⭐️ 🌻如果本文有什么错误的话欢迎在评论区中指正哦💗 🌻看完之后觉得不错的话麻烦动动小手点个赞赞吧👍 🌻与其明天开始,不如现在行动!💪 🌻大家…...
No primary or single unique constructor found for interface java.util.List
1.问题描述 前端 请求的参数 是 query形式, 参数在url中 报错信息: java.lang.IllegalStateException: No primary or single unique constructor found for interface java.util.List2.解决办法 controller中的 请求方法 参数 加上 RequestParam...
C#关于WebService中File.Exists()处理远程路径的异常记录
目录 前言方案一打开网站对应的程序池的高级设置按下图步骤设置凭据重启网站若方案一未能解决,请继续尝试方案二👇 方案二从控制面板进入到 凭据管理器为windows凭据添加凭据点击**Windows凭据**,并点击**添加Windows凭据**键入远程路径的地址…...
JavaWeb_LeadNews_Day10-Xxljob, Redis实现定时热文章
JavaWeb_LeadNews_Day10-Xxljob, Redis实现定时热文章 xxl-job概述windows部署调度中心docker部署调度中心 xxl-job入门案例xxl-job分片广播热点文章定时计算思路分析具体实现热文章计算定时计算 查询文章接口改造来源Gitee xxl-job概述 windows部署调度中心 运行 xxl-job\do…...
【WebRTC---源码篇】(二:二)视频源VideoSourceBase
作用 这个类继承自VideoSourceInterface<webrtc::VideoFrame>模板类,并且可以处理webrtc::VideoFrame class VideoSourceBase : public VideoSourceInterface<webrtc::VideoFrame> 重要成员变量 struct SinkPair {SinkPair(VideoSinkInterface<webrtc::Vid…...
Linux_8_磁盘存储和文件系统
1 磁盘结构 1.1 设备文件 一切皆文件: open(),read(),write(),close() 设备文件:关联至一个设备驱动程序,进而能够跟与之对应硬件设备进行通信 设备号码: 主设备号 major number,标识设备类型 次设备号 minor number,标识同一类型下的不同设备 设备类型:…...
VS + QT 封装带UI界面的DLL
一、创建编译DLL的项目 1.新建Qt Class Liabrary 2.新建项目,选择Qt Widgets Class 3.新建C类,可以在此类里面写算法函数用于调用。 4.下面是添加完Qt窗体类和C类之后的项目截图 5.修改头文件并编译 将uidemo_global.h中的ifdef内容复制到dialog.h上…...
逆向工程-架构真题(二十)
结构化程序设计采用自顶向下、逐步求精及模块化程序设计方法,通过()三种基本控制结构可以构造出任何单入口单出口程序。 顺序、选择和嵌套顺序、分支和循环分支、并发和循环跳转、选择和并发 答案:B 解析: 结构化设…...
Zookeeper 入门
第 1 章 Zookeeper 入门 1.1概述 Zookeeper从设计模式角度来理解:是一个基于观察者模式设计的分布式服务管理框架,它负责存储和管理大家都关心的数据,然后接受观察者的注册,一旦这些数据的状态发生变化,Zookeeper就将…...
记录--前端使用a链接下载内容增加loading效果
这里给大家分享我在网上总结出来的一些知识,希望对大家有所帮助 问题描述:最近工作中出现一个需求,纯前端下载 Excel 数据,并且有的下载内容很多,这时需要给下载增加一个 loading 效果。 代码如下: // util…...
如何获取用户的ip地址
用户的 IP 地址可能会被隐藏或者修改,例如使用代理服务器、VPN 等工具,这样就无法准确获取用户的真实 IP 地址。 除了以上特殊情况,一般情况下 用户访问可能会经过一下链路 : 前端—>nginx—>网关—>服务 。 一般情况下后…...
单片机-控制按键点亮LED灯
1、按键电路图 定义四个按键引脚 1、按键按下 为 输入为低电平 2、按键不按下 IO有上拉电阻,为高电平 // 定义 按键的 管教 sbit KEY1 P3^1; sbit KEY2 P3^0; sbit KEY3 P3^2; sbit KEY4 P3^3; 2、LED灯电路图 LED 输出高电平为亮 // 定义LED灯 管教 sbit LED1…...
微信小程序新版隐私协议弹窗实现最新版
1. 微信小程序又双叒叕更新了 2023.08.22更新: 以下指南中涉及的 getPrivacySetting、onNeedPrivacyAuthorization、requirePrivacyAuthorize 等接口目前可以正常接入调试。调试说明: 在 2023年9月15号之前,在 app.json 中配置 __usePriva…...
GO语言圣经 第五章习题
练习5.1 修改findlinks代码中遍历n.FirstChild链表的部分,将循环调用visit,改成递归调用。 func visit(links []string, n *html.Node) []string {if n nil {return links}if n.Type html.ElementNode && n.Data "a" {for _, a : r…...
用kotlin 开发一个简单的多页面跳转
本文介绍一个简单的安卓应用的页面跳转例子,用的是kotlin。 运行时主页面是一个hello 和Jump 按钮,你按一下jump 按钮就转到 从页面,只是标识从页面。 开始建立一个简单工程,名为hello, 选择的是Empty views Activit…...
记录我的tensorrt 部署yolov8
系统 :ubuntu 18.04 代码 :GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT conda 环境 : GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT cuda : 11.8 …...
什么是用户界面? 优漫动游
什么是用户界面? 用户界面(UI,UserInterface)也称人机界面,是人机交互、操作逻辑和界面表现的整体设计。每一种设计都有其对应的职业角色,其中,人机交互的设计人员叫做用户研究工程师,操作逻辑设计人员叫…...
【Linux】shell脚本忽略错误继续执行
在 shell 脚本中,可以使用 set -e 命令来设置脚本在遇到错误时退出执行。如果你希望脚本忽略错误并继续执行,可以在脚本开头添加 set e 命令来取消该设置。 举例1 #!/bin/bash# 取消 set -e 的设置 set e# 执行命令,并忽略错误 rm somefile…...
智慧医疗能源事业线深度画像分析(上)
引言 医疗行业作为现代社会的关键基础设施,其能源消耗与环境影响正日益受到关注。随着全球"双碳"目标的推进和可持续发展理念的深入,智慧医疗能源事业线应运而生,致力于通过创新技术与管理方案,重构医疗领域的能源使用模式。这一事业线融合了能源管理、可持续发…...
shell脚本--常见案例
1、自动备份文件或目录 2、批量重命名文件 3、查找并删除指定名称的文件: 4、批量删除文件 5、查找并替换文件内容 6、批量创建文件 7、创建文件夹并移动文件 8、在文件夹中查找文件...
Python:操作 Excel 折叠
💖亲爱的技术爱好者们,热烈欢迎来到 Kant2048 的博客!我是 Thomas Kant,很开心能在CSDN上与你们相遇~💖 本博客的精华专栏: 【自动化测试】 【测试经验】 【人工智能】 【Python】 Python 操作 Excel 系列 读取单元格数据按行写入设置行高和列宽自动调整行高和列宽水平…...
学校时钟系统,标准考场时钟系统,AI亮相2025高考,赛思时钟系统为教育公平筑起“精准防线”
2025年#高考 将在近日拉开帷幕,#AI 监考一度冲上热搜。当AI深度融入高考,#时间同步 不再是辅助功能,而是决定AI监考系统成败的“生命线”。 AI亮相2025高考,40种异常行为0.5秒精准识别 2025年高考即将拉开帷幕,江西、…...
Springboot社区养老保险系统小程序
一、前言 随着我国经济迅速发展,人们对手机的需求越来越大,各种手机软件也都在被广泛应用,但是对于手机进行数据信息管理,对于手机的各种软件也是备受用户的喜爱,社区养老保险系统小程序被用户普遍使用,为方…...
无人机侦测与反制技术的进展与应用
国家电网无人机侦测与反制技术的进展与应用 引言 随着无人机(无人驾驶飞行器,UAV)技术的快速发展,其在商业、娱乐和军事领域的广泛应用带来了新的安全挑战。特别是对于关键基础设施如电力系统,无人机的“黑飞”&…...
AD学习(3)
1 PCB封装元素组成及简单的PCB封装创建 封装的组成部分: (1)PCB焊盘:表层的铜 ,top层的铜 (2)管脚序号:用来关联原理图中的管脚的序号,原理图的序号需要和PCB封装一一…...
海云安高敏捷信创白盒SCAP入选《中国网络安全细分领域产品名录》
近日,嘶吼安全产业研究院发布《中国网络安全细分领域产品名录》,海云安高敏捷信创白盒(SCAP)成功入选软件供应链安全领域产品名录。 在数字化转型加速的今天,网络安全已成为企业生存与发展的核心基石,为了解…...
网页端 js 读取发票里的二维码信息(图片和PDF格式)
起因 为了实现在报销流程中,发票不能重用的限制,发票上传后,希望能读出发票号,并记录发票号已用,下次不再可用于报销。 基于上面的需求,研究了OCR 的方式和读PDF的方式,实际是可行的ÿ…...
