Scala的模式匹配

这篇具有很好参考价值的文章主要介绍了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 = 5
    val y: String = x match {
      case 1 => "one"
      case 2 => "two"
      case 3 => "three"
      case _ => "other"
    }
    println(y)

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

    def matchDualOp(op: Char): Int = op match {
      case '+' => a + b
      case '-' => a - b
      case '*' => a * b
      case '/' => a / b
      case '%' => a % b
      case _ => -1
    }

    println(matchDualOp('+'))
    println(matchDualOp('/'))
    println(matchDualOp('\\'))

    println("=========================")

    // 3. 模式守卫
    // 求一个整数的绝对值
    def abs(num: Int): Int = {
      num match {
        case i if i >= 0 => i
        case 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 = 123

x 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 => 0
  case 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 = 123

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

匹配类和对象

匹配对象的例子

/**
 * 对象与对象的属性进行模式匹配:
 *   1.需要定义一个类和伴生对象,在伴生对象中需要定义创建对象的方法apply方法
 *   2. 由于对象直接的比较是地址引用的比较,如果需要使用模式匹配对对象的属性值进行判断,
 *   就需要在伴生对象中定义unapply方法用于结构对象实例。unapply方法用来对对象属性进行拆解
 */
object Test_MatchObject {
  def main(args: Array[String]): Unit = {
    val student = new Student("alice", 19)

    // 针对对象实例的内容进行匹配
    val result = student match {
      case Student("alice", 18) => "Alice, 18"
      case _ => "Else"
    }

    println(result)
  }
}

// 定义类
class Student(val name: String, val age: Int)

// 定义伴生对象
object Student {
  def apply(name: String, age: Int): Student = new Student(name, age)
  // 必须实现一个unapply方法,用来对对象属性进行拆解
  def unapply(student: Student): Option[(String, Int)] = {
    if (student == null){
      None
    } else {
      Some((student.name, student.age))
    }
  }
}
示例二
sealed trait Shape
case class Circle(radius: Double) extends Shape
case class Rectangle(width: Double, height: Double) extends Shape
case object UnknownShape extends Shape

val 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) = tuple

println(s"字符串:$str")
println(s"整数:$num")

在上面的代码中,我们声明了一个元组 tuple,包含两个元素:一个字符串和一个整数。然后,我们使用模式匹配的方式将元组中的值解构并赋给了两个新的变量 strnum。这样,我们就可以通过这两个变量来访问元组中的值。

变量声明时模式匹配案例

object Test03_MatchTupleExtend {
  def main(args: Array[String]): Unit = {
    // 1. 在变量声明时匹配
    val (x, y) = (10, "hello")
    println(s"x: $x, y: $y")

    //变量声明是匹配
    val (a,b) = (100,"hello")
    println(s"a: $a, b: $b")

    val List(first, second, _*) = List(23, 15, 9, 78)
    println(s"first: $first, second: $second")
    // 使用双冒号模式匹配的方式进行赋值
    val fir :: sec :: rest = List(23, 15 , 9, 78)
    println(s"first: $fir, second: $sec, rest: $rest")

    println("=====================")

    // 2. for推导式中进行模式匹配,List[ (String, Int) ],集合list里面是多个二元组
    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 13))

    // 2.1 原本的遍历方式
    for (elem <- list){
      println(elem._1 + " " + elem._2)
    }

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

    println("-----------------------")
    // 2.3 可以不考虑某个位置的变量,只遍历key或者value,比如只遍历,打印元组的第一个元素word,不要count
    for ((word, _) <- list)
      println(word)

    println("-----------------------")

    // 2.4 可以指定某个位置的值必须是多少
    // 指定第一个元素为a的value值打印出来
    for (("a", count) <- list){
      println(count)
    }
  }
}


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

val list: List[String] = List("Hello", "World")

val head :: tail = list

println(s"头部元素:$head")
println(s"剩余元素:$tail")

在上面的代码中,我们声明了一个列表 list,包含两个字符串元素。然后,使用模式匹配的变量声明方式将列表的头部元素赋给变量 head,剩余元素赋给变量 tail。这样,我们就可以分别访问列表的头部元素和剩余元素。

需要注意的是,模式匹配的变量声明在匹配失败时会抛出 MatchError 异常。为了避免这种情况,请确保变量声明与待解构的数据结构具有相同的结构和类型。

匹配对象及样例类

样例类

在Scala中,样例类(Case Class)是一种特殊的类,用于定义不可变的数据模型。样例类,自动默认创建伴生对象,并生成apply方法和解析对象的unapply方法,还实现了equalshashCodetoString等方法。
它具有许多有用的功能,使得数据建模和处理更加简洁和方便。

以下是样例类的特点和使用方式:

  1. 自动创建类的伴生对象:定义样例类时,编译器会自动生成一个与类同名的伴生对象,其中包含了一些常用的方法和属性。

  2. 不可变性:样例类的实例默认是不可变的,即无法在创建后修改其状态。

  3. 默认实现了equalshashCodetoString等方法:编译器会自动生成这些方法的实现,使得比较、哈希和输出对象更加方便。

  4. 模式匹配的支持:样例类通常用于模式匹配,可以方便地匹配和提取类的属性。

下面是一个简单的示例来说明如何定义和使用样例类:

case class Person(name: String, age: Int)

val alice = Person("Alice", 25)
val bob = Person("Bob", 30)

println(alice.name) // 输出: Alice

val olderPerson = alice.copy(age = alice.age + 1)
println(olderPerson) // 输出: Person(Alice, 26)

alice match {
  case Person("Alice", age) => println(s"Alice is $age years old.")
  case Person(name, age) => println(s"$name is $age years old.")
}

上述示例中,定义了一个名为Person的样例类。它有两个属性:nameage。使用样例类的主构造函数可以直接创建对象,而不需要使用new关键字。

可以通过点号.访问对象的属性,如alice.name。还可以使用copy方法创建一个新的对象,同时修改部分属性的值。

match表达式中,可以使用模式匹配来处理不同的Person对象。这使得根据对象的属性进行处理变得更加简单和直观。

总之,样例类提供了一种方便和强大的方式来定义不可变的数据对象,并且自动提供了一些常用方法和模式匹配的支持。它们在函数式编程和数据建模方面非常有用。


样例类使用模式匹配示例代码

/** 样例类:
 * 在Scala中,样例类(Case Class)是一种特殊的类,用于定义不可变的数据模型。
 * 样例类,自动默认创建伴生对象,并生成apply方法和解析对象的unapply方法,
 *还实现了equals、hashCode、toString等方法。
 */
object Test05_MatchCaseClass {
  def main(args: Array[String]): Unit = {
    val student = Student1("alice", 18)

    // 针对对象实例的内容进行匹配
    val result = student match {
      case Student1("alice", 18) => "Alice, 18"
      case _ => "Else"
    }

    println(result)
  }
}
// 定义样例类
case class Student1(name: String, age: Int)

在 Scala 中,可以使用模式匹配来匹配各种类型的对象,包括普通类和样例类。其中,样例类是一种特殊的类,它专门用于模式匹配,因为编译器会自动生成带有模式匹配相关方法的代码。以下是一个示例:

sealed trait Fruit
case class Apple(color: String) extends Fruit
case class Banana(length: Int) extends Fruit
case object UnknownFruit extends Fruit

val 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 Location

def printCapital(location: Location): Unit = {
  location match {
    case Country(_, City(capital)) => println(s"首都是$capital")
    case _ => println("未知位置")
  }
}

在上面的代码中,我们定义了一个 Location 类及其两个子类 City 和 Country。Country 类包含一个 City 类的实例作为首都。通过嵌套的模式匹配,我们可以提取和打印出国家的首都。文章来源地址https://www.toymoban.com/news/detail-691573.html

到了这里,关于Scala的模式匹配的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • 十分钟带汝入门大数据开发语言Scala

    大家好,我是百思不得小赵。 创作时间:2022 年 6 月 7 日 博客主页: 🔍点此进入博客主页 —— 新时代的农民工 🙊 —— 换一种思维逻辑去看待这个世界 👀 今天是加入CSDN的第1193天。觉得有帮助麻烦👏点赞、🍀评论、❤️收藏 Scala是一门多范式的编程语言,一种类似Ja

    2024年02月02日
    浏览(53)
  • spark底层为什么选择使用scala语言开发

    基于Scala的语言特性 集成性:Scala 是一种运行在 Java 虚拟机(JVM)上的静态类型编程语言,可以与 Java 代码无缝集成。由于 Spark 涉及到与大量 Java 生态系统的交互,例如 Hadoop、Hive 等,使用 Scala 可以方便地与这些组件进行集成和交互。 函数式编程支持:Scala 是一种面向函数

    2024年02月10日
    浏览(54)
  • 大数据开发之Scala

    scala将面向对象和函数式编程结合成一种简洁的高级语言 特点 1、scala和java一样属于jvm语言,使用时都需要先编译为class字节码文件,并且scala能够直接调用java的类库 2、scala支持两种编程范式面向对象和函数式编程 3、scala语言更加简洁高效 Scala注释使用和Java完全一样。 注释

    2024年01月23日
    浏览(37)
  • Scala大数据开发

    本文原创作者:谷哥的小弟 作者博客地址:http://blog.csdn.net/lfdfhl 在此,简要介绍 Scala 的基本信息和情况。 Scala 源自于英语单词scalable,表示可伸缩的、可扩展的含义。 Scala编程语言是由瑞士洛桑联邦理工学院(EPFL )的Martin Odersky于2001年开始设计并研发的。 Martin Odersky主要

    2024年04月11日
    浏览(28)
  • 大数据技术——使用IDEA开发Scala程序

    一、使用IDEA开发WordCount程序... 3 二、实验目的... 3 三、实验要求... 3 四、实验环境... 3 五、实验步骤... 3 4.1.1启动IDEA并创建一个新项目WordCount 3 4.1.2为WordCount项目添加Scala框架支持... 7 4.1.3数据准备... 8 4.1.4设置项目目录... 9 4.1.5新建Scala代码文件... 10 4.1.6配置pom.xml文件... 12

    2024年02月09日
    浏览(39)
  • 大数据Spark SparkSession的3种创建方式 Scala语言实现

    SparkSession是Apache Spark 2.0版本引入的一个编程接口,用于与Spark进行交互。它是Spark应用程序的入口点,提供了一种方便的方式来创建DataFrame、DataSet和SQLContext等数据结构,并且可以配置各种Spark应用程序的选项。SparkSession还管理了Spark应用程序的运行环境,包括Spark集群的连接,

    2023年04月20日
    浏览(36)
  • Spark大数据分析与实战笔记(第一章 Scala语言基础-2)

    Spark是专为大规模数据处理而设计的快速通用的计算引擎,它是由Scala语言开发实现的,关于大数据技术,本身就是计算数据,而Scala既有面向对象组织项目工程的能力,又具备计算数据的功能,同时Spark和Scala的紧密集成,本书将采用Scala语言开发Spark程序,所以学好Scala将有助

    2024年02月11日
    浏览(59)
  • Spark大数据分析与实战笔记(第一章 Scala语言基础-1)

    Spark是专为大规模数据处理而设计的快速通用的计算引擎,它是由Scala语言开发实现的,关于大数据技术,本身就是计算数据,而Scala既有面向对象组织项目工程的能力,又具备计算数据的功能,同时Spark和Scala的紧密集成,本书将采用Scala语言开发Spark程序,所以学好Scala将有助

    2024年02月11日
    浏览(62)
  • Spark大数据分析与实战笔记(第一章 Scala语言基础-3)

    对于每一门编程语言来说,数组(Array)都是重要的数据结构之一,主要用来存储数据类型相同的元素。Scala中的数组分为定长数组和变长数组,定义定长数组,需要使用new,而定义变长数组时,则需要导包 import scala.collection.mutable.ArrayBuffer 。 数组(Array)主要用来存储

    2024年02月10日
    浏览(60)
  • 你知道Scala编程语言吗?Scala基础教程【建议收藏】

    作者:i阿极 作者简介:Python领域新星作者、多项比赛获奖者:博主个人首页 😊😊😊如果觉得文章不错或能帮助到你学习,可以点赞👍收藏📁评论📒+关注哦!👍👍👍 📜📜📜如果有小伙伴需要数据集和学习交流,文章下方有交流学习区!一起学习进步!💪 Scala是一种

    2023年04月08日
    浏览(80)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包