Scala笔记--模式匹配
Posted 幼儿园园草
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了Scala笔记--模式匹配相关的知识,希望对你有一定的参考价值。
文章目录
模式匹配(pattern matching)在Scala被广泛使用的特性中排在第二位,仅次于函数值和闭包。Scala对于模式匹配的出色支持意味着,在并发编程中在处理Actor接收到的消息时,将会大量地使用它。
Scala的模式匹配非常灵活,可以匹配字面量和常量,以及使用通配符匹配任意的值、元组和列表,甚至还可以根据类型以及判定守卫来进行匹配。
1 基础用法
scala的模式匹配类似于Java的Switch语句,但是比Switch语句强大得多。
1.1 入门案例
val i: Int = 5
val s: String = i match {
case 1 => "one"
case 2 => "two"
case 3 => "three"
case 4 => "four"
case _ => "other"
}
println(s)
1.2 匹配函数参数
我们可以通过匹配函数的参数来进一步简化二元加减乘除等操作。
def matchDualOp(a: Int, b: Int, op: Char): Int = op match {
case '+' => a + b
case '-' => a - b
case '*' => a * b
case '/' => a / b
case _ => -1
}
println(matchDualOp(2, 1, '+'))
println(matchDualOp(2, 1, '-'))
println(matchDualOp(2, 1, '*'))
println(matchDualOp(2, 1, '/'))
// println(matchDualOp(2,0,'/')) // 报错 / by zero
1.3 模式守卫
1.2的例子其实有些地方需要改进,因为除法操作中,b不能为0,所以这里可以使用模式守卫进行改进。
def matchDualOp_(a: Int, b: Int, op: Char): Int = op match {
case '+' => a + b
case '-' => a - b
case '*' => a * b
case '/' if b != 0 => a / b
case _ => {
print("无法匹配")
-1
}
}
println(matchDualOp_(2, 1, '+'))
println(matchDualOp_(2, 1, '-'))
println(matchDualOp_(2, 1, '*'))
println(matchDualOp_(2, 1, '/'))
println(matchDualOp_(2, 0, '/'))
2 集合匹配
2.1 匹配常量
def describeConst(x: Any): String = x match {
case 1 => "Int one"
case "hello" => "String hello"
case true => "Boolean true"
case '+' => "Char +"
case _ => ""
}
println(describeConst("hello"))
println(describeConst('+'))
println(describeConst(0.3))
2.2 匹配数据类型
def describeType(x: Any): String = x match {
case i: Int => "Int " + i
case s: String => "String " + s
case list: List[String] => "List " + list
case array: Array[Int] => "Array[Int] " + array.mkString(",")
case a => "Something else: " + a
}
println(describeType(35))
println(describeType("hello"))
println(describeType(List("hi", "hello")))
println(describeType(List(2, 23)))
println(describeType(Array("hi", "hello")))
println(describeType(Array(2, 23)))
2.3 匹配数组
for (arr <- List(
Array(0),
Array(1, 0),
Array(0, 1, 0),
Array(1, 1, 0),
Array(2, 3, 7, 15),
Array("hello", 1, 30),
)) {
val result:String = arr match {
case Array(0) => "0"
case Array(1, 0) => "Array(1, 0)"
case Array(x, y) => "Array: " + x + ", " + y // 匹配两元素数组
case Array(0, _*) => "以0开头的数组"
case Array(x, 1, z) => "中间为1的三元素数组"
case _ => "something else"
}
println(result)
2.4 匹配列表
for (list <- List(
List(0),
List(1, 0),
List(0, 0, 0),
List(1, 1, 0),
List(88),
List("hello")
)) {
val result:String = list match {
case List(0) => "0"
case List(x, y) => "List(x, y): " + x + ", " + y
case List(0, _*) => "List(0, ...)"
case List(a) => "List(a): " + a
case _ => "something else"
}
println(result)
}
2.5 匹配元组
for (tuple <- List(
(0, 1),
(0, 0),
(0, 1, 0),
(0, 1, 1),
(1, 23, 56),
("hello", true, 0.5)
)){
val result = tuple match {
case (a, b) => "" + a + ", " + b
case (0, _) => "(0, _)"
case (a, 1, _) => "(a, 1, _) " + a
case (x, y, z) => "(x, y, z) " + x + " " + y + " " + z
case _ => "something else"
}
println(result)
2.6 通用匹配
这种方式很像python的接收参数的用法
package com.lrm.demo08
/**
* @author RuiMing Lin
* @date 2021-06-05 10:06
* @description 元祖匹配
*/
object demo3 {
def main(args: Array[String]): Unit = {
// 1. 在变量声明时匹配
val (x, y) = (10, "hello")
println(s"x: $x, y: $y")
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推导式中进行模式匹配
val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 13))
// 2.1 原本的遍历方式
for (elem <- list){
println(elem._1 + " " + elem._2)
}
println("-----------------------")
// 2.2 将List的元素直接定义为元组,对变量赋值
for ((word, count) <- list ){
println(word + ": " + count)
}
println("-----------------------")
// 2.3 可以不考虑某个位置的变量,只遍历key或者value
for ((word, _) <- list)
println(word)
println("-----------------------")
// 2.4 可以指定某个位置的值必须是多少
for (("a", count) <- list){
println(count)
}
}
}
3 对象匹配
3.1 unapply
做对象的模式匹配时,必须实现一个unapply方法,用来对对象属性进行拆解
package com.lrm.demo08
/**
* @author RuiMing Lin
* @date 2021-06-05 10:07
* @description
*/
object demo4 {
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))
}
}
}
3.2 样例类
case类是特殊的类,可以使用case表达式来进行模式匹配。case类很简洁,并且容易创建,它将其构造参数都公开为值。可以使用case类来创建轻量级值对象,或者类名和属性名都富有意义的数据持有者。
package com.lrm.demo08
/**
* @author RuiMing Lin
* @date 2021-06-05 10:07
* @description 样例类
*/
object demo5 {
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笔记--模式匹配的主要内容,如果未能解决你的问题,请参考以下文章