Scala学习小计 - 什么是模式匹配(pattern-matchin)?
文章目录
- 简介
- 常量匹配
- 变量匹配
- 通配符匹配
- 构造器模式
- 类型匹配
- 变量绑定匹配
简介
模式匹配(pattern-matching),什么是模式(pattern)?,这里的模式用于描述一个结构的组成。
这个pattern和正则里的pattern相似,不过适用范围更广,可以针对各种类型的数据结构,不像正则表达只是针对字符串。
比如:List("a", _, _*)
也是个pattern,表示第一个元素是 "a"
,后续一个或多个元素的 List
。
简单解读下:
- 首先这个模式首先声明它只会匹配
List
类型的数据结构。 - 其次这个List的第一个元素必须是字符串
"a"
。 - 然后通过
_
占位符来表示,第二位元素必须存在,但是不限制其数据类型、数据内容等等。 - 最后
_*
表示后续的元素也是类型不限,内容不限。*
表示个数都是0或多个的。
在Scala中会经常应用到这个模式匹配的,它能减少if else的判断,能快速的帮你获取到想要的结果情况,并进行下一步的处理。
下面是Scala中的常用例子:
# 匹配一个List,它由三个元素组成,第一个元素为1,第二个元素为2,第三个元素为3
scala> List(1, 2, 3) match { case List(1, 2, 3) => println("ok") }
ok# 匹配一个List,它至少由一个元素组成,第一个元素为1
scala> List(1, 2, 3) match { case List(1, _*) => println("ok") }
ok# 匹配一个List,它由三个元素组成,第一个元素为“a",第二个元素任意类型,第三个元素为"c"
scala> List("a", "b", "c") match{ case List("a", _, "c") => println("ok") }
ok# 当然模式也不仅仅是表示某种结构的,还可以是常量,或类型,如:
scala> val a = 10
a: Int = 10# 常量模式,如果a与100相等则匹配成功
scala> a match { case 10 => println("ok") }
ok# 类型模式,如果a是Int类型就匹配成功
scala> a match { case _:Int => println("ok") }
ok
常量匹配
# 例子中case 了一个常量值,然后去匹配s的值。和if语句的效果很像。
scala> val site = "abc"
scala> site match { case "abc" => print("ok") }
scala> val ABC = "abc"
# 注意:匹配模式这里常量必须以大写字母开头。否则 case abc 的话,会将s的赋值到abc身上,而不是模式匹配。
scala> def m(s: String) = s match { case ABC => println("ok") }
scala> m("ab") # 这里会报异常,因为没有case到当前的情况,导致无法处理
scala> m("abc") # 得到ok
变量匹配
变量模式匹配,没有判断变量值,而是单纯的把 site 给赋值到变量 whateverName 上而已。所以这里一般总会匹配成功。
注意:匹配变量这里必须是小写的字母开头,否则会认为是上面的常量匹配。
Future对象的 Future().flatMap { case XX }
就可以理解为变量匹配。
scala> site match { case aaa => println(aaa) }
abc
scala> List(1, 2) match { case List(x, 2) => println(x) }
1
通配符匹配
通配符用下划线表示:_
,可以理解成一个特殊的变量或占位符。通配符通常用于代表所不关心的部分,它不像变量模式可以后续的逻辑中使用这个变量。
单纯的通配符模式通常在模式匹配的最后一行出现,case _ =>
它可以匹配任何对象,用于处理所有其它匹配不成功的情况。这种会处理一些位置的匹配结果情况,从而减少报出异常的情况。
通配符模式也常和其他模式组合使用:
List(1, 2, 3) match {case List(_, _, 3) => println("ok") }
# 上面的 List(_,_,3) 里用了2个通配符表示第一个和第二个元素,这2个元素可以是任意类型
构造器模式
就是去指定一个变量或者class的构造方法的构造规则,然后筛选出符合该匹配规则的变量(或者实例)
# 定义一个case class
scala> case class Person(name: String, age:Int)
defined class Person
# 通过构造器创建一个实例
scala> Person("hanmeimei", 25)
res20: Person = Person(hanmeimei,25)
# 匹配模式的时候可以直接实例的具体内容
scala> res20 match { case Person(_, 25) => print("ok")}
ok
# 也可以在匹配模式的时候,指定赋值的变量,或者声明变量的类型提供更精确的匹配
scala> res20 match { case Person(name, hisAge:Int) => print(name + "-" + hisAge)}
hanmeimei-25
类型匹配
就是判断对象是否是某种类型(在匹配规则处指定变量的类型,而变量可以指定名称,也可以使用通配符):
scala> "hello" match {case _:String => println("ok") }
跟 isInstanceOf
判断类型的效果一样,需要注意的是Scala匹配泛型时要注意,比如:
def m(a: Any) = a match { case a :List[String] => println("success")case _ => println("failed")
}
如果使用了泛型,它会被擦拭掉,如同Java的做法,所以上面的 List[String]
里的 String
运行时并不能检测
m(List("A"))
和 m(List(2))
都可以匹配成功。实际上上面的语句编译时就会给出警告,但并不出错。
通常对于泛型直接用通配符替代,上面的写为 case a : List[_] =>
注意:针对带有泛型参数的类型匹配,改为构造器模式可以绕开;
或对泛型参数声明 Manifest/TypeTag 是可以在运行时保持泛型参数类型的信息的。
变量绑定匹配
scala> case class Tree(name:String, tree:Tree)
defined class Treescala> Tree("node_1", null)
res26: Tree = Tree(node_1,null)scala> Tree("root", res26)
res27: Tree = Tree(root,Tree(node_1,null))scala> res27 match { case Tree(name, Tree(nodeName, _)) => print(s"$name - $nodeName") }
root - node_1
scala> res27 match { case Tree(name, t@Tree(nodeName, _)) => print(s"$name - $nodeName - $t") }
root - node_1 - Tree(node_1,null)
用@符号将匹配到的数据绑定到t变量上,只有匹配成功才会绑定。
Scala学习小计 - 什么是模式匹配(pattern-matchin)?相关推荐
- 【计算机本科补全计划】Mysql 学习小计(2)
正文之前 昨天下午写了篇 Mysql学习小计,结果出乎意料的受欢迎?变相刺激了我多写点 Mysql?好吧,如尔所愿.我晚上反正还不知道学点啥,就把今天看的那个菜鸟教程学完吧,到时候估计一点了,就可以睡 ...
- 【计算机本科补全计划】Mysql 学习小计(3)
正文之前 想到自己每天中午还要玩一小时手机,就自责不已,今天看成甲的好好学习一书,颇有收获,晚上写给大伙看,现在还是谢谢 Mysql,到了后面感觉越来越难了呢!! 正文 Mysql 事务 Mysql ...
- 学习小计(部分摘自cocos官方文档)1
1.AutoPolygon 裁剪矩形图片的透明部分,使资源所占空间更小. AutoPolygon 是一个工具类,它可以在程序运行时,通过跟踪关键点和三角测量,将一个矩形图像划分成一系列小三角形块 ...
- NAO机器人学习小计
NAO APIs nao的接口全部以AL开头,全部继承自ALModule,它被包含在<alcommon/almodule.h>中. 下面是ALModule的主要methods. ALMod ...
- js学习小计6-慎用return false;
我们总是习惯用return false;来阻止ie6下a标签写了href="javascript:;"还会刷新页面,或者用来阻止冒泡. 但我们忽略了retun false;包含了两 ...
- js学习小计1-onbeforeunload
作用:页面关闭或刷新时候弹出类似confirm的弹窗,确定是否刷新或关闭 一般写法: 1.html中,<body οnbefοreunlοad="return 'sure?'" ...
- 【计算机本科补全计划】Mysql 学习小计(1)
正文之前 以后是要做大数据的人,如果连结构化的数据库都不会的话,那岂不是笑死人?所以果断靠着当年兴趣盎然的时候学的那点基础来复习一下,发现果然学过一遍再来复习那基本就是高中学一段内容看书与翻书的区别, ...
- TweenMax学习小计
TweenMax是一款前端动画插件,可以做出很多效果,灵活性很高,最近闲暇之余学了一下,顺便做点记录. 插件的安装很简单,直接用script引入即可使用: <script src=". ...
- java开发nao机器人,NAO机器人学习小计
NAO APIs nao的接口全部以AL开头,全部继承自ALModule,它被包含在中. 下面是ALModule的主要methods. ALModule APIs namespace : AL #in ...
最新文章
- python工具使用笔记
- Linux工业嵌入式应用
- AWS — AWS 上的 5G 网络及 MEC 边缘计算商业案例
- java项目性能测试过程记录
- modelsim仿真中遇到的问题
- scala连接postgre数据库
- 一个超轻量级工作流引擎:Workflow-Core
- 前沿 | 使用Transformers进行端到端目标识别
- 数据结构(十七)最小生成树
- DSP编程 单片机编程 开关电源设计
- Comsol学习——经典案例:水净化反应器
- 微服务业务日志收集方案
- Java第十一章总结 枚举与泛型
- webshell检测方式深度剖析---RASP(taint扩展)
- 什么是Scrum团队?
- [今日名人回顾]计算机之父—冯·诺依曼
- java商城开发可以说是日臻完美
- Python编程-从入门到实践第15章课后习题详解
- 服务器机房单线和双线机房该如何选择?
- 最火热的东南亚跨境电商平台Shopee、Lazada,为什么必须要做补单