当前位置: 首页 > news >正文

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 相加。

需要注意的是,在模式匹配中,每个匹配分支都必须满足类型一致性和互斥性,以避免出现匹配二义性的情况。

模式守卫

  1. 说明
    如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。
  2. 代码示例
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,包含两个元素:一个字符串和一个整数。然后,我们使用模式匹配的方式将元组中的值解构并赋给了两个新的变量 strnum。这样,我们就可以通过这两个变量来访问元组中的值。

除了元组,还可以在变量声明中匹配其他数据结构,比如列表、数组等。示例如下:

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 样例类及两个子类 AppleBanana,还有一个对象 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 语法&#xff1a;下面是java中switch代码&#xff1a; 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.创建调用者三、结果被调用者服务&#xff1a;调用者服务&#xff1a; 总结 前言 欢迎来到本篇博客&#xff0c;这是一个关于HttPClient的入门案例的指南。&#x1f389; 在今天的网络世界中&#xff0c;与服务器进行数据…...

STS4 New 安装Spring Bean Configuration File

背景介绍 在创建spring项目后&#xff0c;如果想想创建spring bean Configuration的时候&#xff0c;发下菜单没有这个选项&#xff0c;需要通过下载Spring Roo插件可满足该操作。 参考案例 参考地址&#xff1a; STS4 New 菜单没有Spring Bean Configuration File选项_SQZHA…...

Java经典面试题(异或运算)

不爱生姜不吃醋⭐️⭐️⭐️ &#x1f33b;如果本文有什么错误的话欢迎在评论区中指正哦&#x1f497; &#x1f33b;看完之后觉得不错的话麻烦动动小手点个赞赞吧&#x1f44d; &#x1f33b;与其明天开始&#xff0c;不如现在行动&#xff01;&#x1f4aa; &#x1f33b;大家…...

No primary or single unique constructor found for interface java.util.List

1.问题描述 前端 请求的参数 是 query形式&#xff0c; 参数在url中 报错信息&#xff1a; java.lang.IllegalStateException: No primary or single unique constructor found for interface java.util.List2.解决办法 controller中的 请求方法 参数 加上 RequestParam...

C#关于WebService中File.Exists()处理远程路径的异常记录

目录 前言方案一打开网站对应的程序池的高级设置按下图步骤设置凭据重启网站若方案一未能解决&#xff0c;请继续尝试方案二&#x1f447; 方案二从控制面板进入到 凭据管理器为windows凭据添加凭据点击**Windows凭据**&#xff0c;并点击**添加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() 设备文件:关联至一个设备驱动程序&#xff0c;进而能够跟与之对应硬件设备进行通信 设备号码: ​ 主设备号 major number,标识设备类型​ 次设备号 minor number,标识同一类型下的不同设备 设备类型:…...

VS + QT 封装带UI界面的DLL

一、创建编译DLL的项目 1.新建Qt Class Liabrary 2.新建项目&#xff0c;选择Qt Widgets Class 3.新建C类&#xff0c;可以在此类里面写算法函数用于调用。 4.下面是添加完Qt窗体类和C类之后的项目截图 5.修改头文件并编译 将uidemo_global.h中的ifdef内容复制到dialog.h上…...

逆向工程-架构真题(二十)

结构化程序设计采用自顶向下、逐步求精及模块化程序设计方法&#xff0c;通过&#xff08;&#xff09;三种基本控制结构可以构造出任何单入口单出口程序。 顺序、选择和嵌套顺序、分支和循环分支、并发和循环跳转、选择和并发 答案&#xff1a;B 解析&#xff1a; 结构化设…...

Zookeeper 入门

第 1 章 Zookeeper 入门 1.1概述 Zookeeper从设计模式角度来理解&#xff1a;是一个基于观察者模式设计的分布式服务管理框架&#xff0c;它负责存储和管理大家都关心的数据&#xff0c;然后接受观察者的注册&#xff0c;一旦这些数据的状态发生变化&#xff0c;Zookeeper就将…...

记录--前端使用a链接下载内容增加loading效果

这里给大家分享我在网上总结出来的一些知识&#xff0c;希望对大家有所帮助 问题描述&#xff1a;最近工作中出现一个需求&#xff0c;纯前端下载 Excel 数据&#xff0c;并且有的下载内容很多&#xff0c;这时需要给下载增加一个 loading 效果。 代码如下&#xff1a; // util…...

如何获取用户的ip地址

用户的 IP 地址可能会被隐藏或者修改&#xff0c;例如使用代理服务器、VPN 等工具&#xff0c;这样就无法准确获取用户的真实 IP 地址。 除了以上特殊情况&#xff0c;一般情况下 用户访问可能会经过一下链路 &#xff1a; 前端—>nginx—>网关—>服务 。 一般情况下后…...

单片机-控制按键点亮LED灯

1、按键电路图 定义四个按键引脚 1、按键按下 为 输入为低电平 2、按键不按下 IO有上拉电阻&#xff0c;为高电平 // 定义 按键的 管教 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更新&#xff1a; 以下指南中涉及的 getPrivacySetting、onNeedPrivacyAuthorization、requirePrivacyAuthorize 等接口目前可以正常接入调试。调试说明&#xff1a; 在 2023年9月15号之前&#xff0c;在 app.json 中配置 __usePriva…...

GO语言圣经 第五章习题

练习5.1 修改findlinks代码中遍历n.FirstChild链表的部分&#xff0c;将循环调用visit&#xff0c;改成递归调用。 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 开发一个简单的多页面跳转

本文介绍一个简单的安卓应用的页面跳转例子&#xff0c;用的是kotlin。 运行时主页面是一个hello 和Jump 按钮&#xff0c;你按一下jump 按钮就转到 从页面&#xff0c;只是标识从页面。 开始建立一个简单工程&#xff0c;名为hello&#xff0c; 选择的是Empty views Activit…...

记录我的tensorrt 部署yolov8

系统 &#xff1a;ubuntu 18.04 代码 &#xff1a;GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT conda 环境 &#xff1a; GitHub - noahmr/yolov5-tensorrt: Real-time object detection with YOLOv5 and TensorRT cuda : 11.8 …...

什么是用户界面? 优漫动游

什么是用户界面&#xff1f; 用户界面(UI&#xff0c;UserInterface)也称人机界面&#xff0c;是人机交互、操作逻辑和界面表现的整体设计。每一种设计都有其对应的职业角色&#xff0c;其中&#xff0c;人机交互的设计人员叫做用户研究工程师&#xff0c;操作逻辑设计人员叫…...

(LeetCode 每日一题) 3442. 奇偶频次间的最大差值 I (哈希、字符串)

题目&#xff1a;3442. 奇偶频次间的最大差值 I 思路 &#xff1a;哈希&#xff0c;时间复杂度0(n)。 用哈希表来记录每个字符串中字符的分布情况&#xff0c;哈希表这里用数组即可实现。 C版本&#xff1a; class Solution { public:int maxDifference(string s) {int a[26]…...

【杂谈】-递归进化:人工智能的自我改进与监管挑战

递归进化&#xff1a;人工智能的自我改进与监管挑战 文章目录 递归进化&#xff1a;人工智能的自我改进与监管挑战1、自我改进型人工智能的崛起2、人工智能如何挑战人类监管&#xff1f;3、确保人工智能受控的策略4、人类在人工智能发展中的角色5、平衡自主性与控制力6、总结与…...

线程与协程

1. 线程与协程 1.1. “函数调用级别”的切换、上下文切换 1. 函数调用级别的切换 “函数调用级别的切换”是指&#xff1a;像函数调用/返回一样轻量地完成任务切换。 举例说明&#xff1a; 当你在程序中写一个函数调用&#xff1a; funcA() 然后 funcA 执行完后返回&…...

spring:实例工厂方法获取bean

spring处理使用静态工厂方法获取bean实例&#xff0c;也可以通过实例工厂方法获取bean实例。 实例工厂方法步骤如下&#xff1a; 定义实例工厂类&#xff08;Java代码&#xff09;&#xff0c;定义实例工厂&#xff08;xml&#xff09;&#xff0c;定义调用实例工厂&#xff…...

【2025年】解决Burpsuite抓不到https包的问题

环境&#xff1a;windows11 burpsuite:2025.5 在抓取https网站时&#xff0c;burpsuite抓取不到https数据包&#xff0c;只显示&#xff1a; 解决该问题只需如下三个步骤&#xff1a; 1、浏览器中访问 http://burp 2、下载 CA certificate 证书 3、在设置--隐私与安全--…...

【android bluetooth 框架分析 04】【bt-framework 层详解 1】【BluetoothProperties介绍】

1. BluetoothProperties介绍 libsysprop/srcs/android/sysprop/BluetoothProperties.sysprop BluetoothProperties.sysprop 是 Android AOSP 中的一种 系统属性定义文件&#xff08;System Property Definition File&#xff09;&#xff0c;用于声明和管理 Bluetooth 模块相…...

从零开始打造 OpenSTLinux 6.6 Yocto 系统(基于STM32CubeMX)(九)

设备树移植 和uboot设备树修改的内容同步到kernel将设备树stm32mp157d-stm32mp157daa1-mx.dts复制到内核源码目录下 源码修改及编译 修改arch/arm/boot/dts/st/Makefile&#xff0c;新增设备树编译 stm32mp157f-ev1-m4-examples.dtb \stm32mp157d-stm32mp157daa1-mx.dtb修改…...

TRS收益互换:跨境资本流动的金融创新工具与系统化解决方案

一、TRS收益互换的本质与业务逻辑 &#xff08;一&#xff09;概念解析 TRS&#xff08;Total Return Swap&#xff09;收益互换是一种金融衍生工具&#xff0c;指交易双方约定在未来一定期限内&#xff0c;基于特定资产或指数的表现进行现金流交换的协议。其核心特征包括&am…...

【Zephyr 系列 10】实战项目:打造一个蓝牙传感器终端 + 网关系统(完整架构与全栈实现)

🧠关键词:Zephyr、BLE、终端、网关、广播、连接、传感器、数据采集、低功耗、系统集成 📌目标读者:希望基于 Zephyr 构建 BLE 系统架构、实现终端与网关协作、具备产品交付能力的开发者 📊篇幅字数:约 5200 字 ✨ 项目总览 在物联网实际项目中,**“终端 + 网关”**是…...

学习STC51单片机32(芯片为STC89C52RCRC)OLED显示屏2

每日一言 今天的每一份坚持&#xff0c;都是在为未来积攒底气。 案例&#xff1a;OLED显示一个A 这边观察到一个点&#xff0c;怎么雪花了就是都是乱七八糟的占满了屏幕。。 解释 &#xff1a; 如果代码里信号切换太快&#xff08;比如 SDA 刚变&#xff0c;SCL 立刻变&#…...