话说kmp模式匹配算法 什么是模式

设计模式 - 文章 - 伯乐在线让天下没有难学的技术
话说模式匹配(8) 一个抽取器的例子
话说模式匹配(8) 一个抽取器的例子
一个抽取器的例子
目前List的序列模式(sequence pattern)可以支持对前边若干元素的匹配,比如:List(1,2,3,_*),如果想要实现 List(_*, lastEle) 这样的形式,就需要通过自定义一个抽取器来实现了
// 自定义Extractor
object Append {
// 接受List结构
def unapply[A] (l: List[A]) = {
// 返回Tuple2:前边的若干元素和最后一个元素
Some( (l.init, l.last) )
抽取器里的unapply方法,入参对应你想要进行匹配的对象,出参则是解构后的元素。
比如 list match { case Append(x,y) =& } 里面的list对应unapply的入参,x,y对应unapply方法的出参。
为什么unapply方法的返回结果大多都使用Some包装一下,这其实是unapply方法返回值的一些:
返回Boolean,那么匹配时 case A() 里面的true不用写(也不能写)
若原本想要返回类型为T,则使用Option[T],这样是为了匹配时能够判断是否成功,Some[T] 成功,None不成功
若原本想要返回一组T1,…Tn,则使用Option[(T1,…Tn)]
现在看看上面自定义抽取器的使用例子:
scala& (1 to 9).toList match{ case _ Append 9 =& println("OK") }
scala& (1 to 9).toList match{ case x Append 8 Append 9 =& println("OK") }
上面使用了中缀写法,也可以写成普通的构造方式,只是看起来没有上面的舒服
scala& (1 to 9).toList match{ case Append(Append(_,8),9) =& println("OK") }
另外,如果觉得Append这个名字太啰嗦,抽取器object单例名称也可以用符号表达,比如用”:&“来表示
object :& {
// unapply ...
这样对匹配时的表达显得更简短一些
scala& (1 to 9).toList match{ case x :& 8 :& 9 =& println("OK") }
另外,以”:“结尾的符号支持从右到左的操作方式,List的子类就采用了“::”这样的名称,以方便模式匹配(当然也是因为早期的一些函数式语言里,如ML里已经定义了::的形式,scala只是延续而已)。
原创文章,转载请注明: 转载自本文链接地址:
王宏江,阿里巴巴技术专家。
Latest posts by hongjiang ()
Related posts:
(1 votes, average: 4.00 out of 5)
Loading...话说模式匹配:什么是模式?
一些刚从java转到scala的同学在开发的过程中犹如深陷沼泽,因为很多的概念或风格不确定,scala里有很多的坑,模式匹配也算一个。我整理了一下自己所理解的概念,以及一些例子。这个系列最好有些scala的基本经验,或者接触过一些其他函数式语言。
要理解模式匹配(pattern-matching),先把这两个单词拆开,先理解什么是模式(pattern),这里所讲的模式并不是设计模式里的模式。
而是数据结构上的,这个模式用于描述一个结构的组成。
我们很容易联想到“正则表达”里的模式,不错,这个pattern和正则里的pattern相似,不过适用范围更广,可以针对各种类型的数据结构,不像正则表达只是针对字符串。
比如正则表达式里 “^A.*” 这个pattern 表示以A开头、后续一个或多个字符组成的字符串;
List(“A”, _,
_*) 也是个pattern,表示第一个元素是”A”,后续一个或多个元素的List。
狭义的看,模式可以当作对某个类型,其内部数据在结构上抽象出来的表达式。如上面的List(“A”, _, _*) 就是一种List结构的pattern。
模式匹配(pattern-matching)则是匹配变量是否符合这种pattern。比如List(“A”,”B”)和List(“A”,”X”,”Y”) 就符合上面的pattern,而List(“X”)则不符合。
直观的看几个例子:
// 匹配一个数组,它由三个元素组成,第一个元素为1,第二个元素为2,第三个元素为3
scala& Array(1,2,3) match { case Array(1,2,3) =& println(“ok”)}
// 匹配一个数组,它至少由一个元素组成,第一个元素为1
scala& Array(1,2,3) match { case Array(1,_*) =& println(“ok”)}
// 匹配一个List,它由三个元素组成,第一个元素为“A”,第二个元素任意类型,第三个元素为”C”
scala& List(“A”,”B”,”C”) match{ case List(“A”,_,”C”) =& println(“ok”) }
例子中的:Array(1,2,3) ,List(“A”,_,”C”) 等都是模式,表示由指定元素组成的某种类型。
当然模式也不仅仅是表示某种结构的,还可以是常量,或类型,如:
scala& val a = 100
a: Int = 100
// 常量模式,如果a与100相等则匹配成功
scala& a match { case 100 =& println(“ok”) }
// 类型模式,如果a是Int类型就匹配成功
scala& a match { case _:Int =& println(“ok”) }
在 scala里对pattern有明确的定义,在形式上有以下几种pattern:
1) 常量模式(constant patterns) 包含常量变量和常量字面量
scala& val site = “”
scala& site match { case “” =& println(“ok”) }
scala& val ALIBABA=””
scala& def foo(s:String) { s match { case ALIBABA =& println(“ok”) } } //注意这里常量必须以大写字母开头
常量模式和普通的 if 比较两个对象是否相等(equals) 没有区别,并没有感觉到什么威力
2) 变量模式(variable patterns)
确切的说单纯的变量模式没有匹配判断的过程,只是把传入的对象给起了一个新的变量名。
scala& site match { case whateverName =& println(whateverName) }
上面把要匹配的 site对象用 whateverName 变量名代替,所以它总会匹配成功。
不过这里有个约定,对于变量,要求必须是以小写字母开头,否则会把它对待成一个常量变量,
比如上面的whateverName 如果写成WhateverName 就会去找这个WhateverName的变量,如果找到则比较相等性,找不到则出错。
变量模式通常不会单独使用,而是在多种模式组合时使用,比如 List(1,2) match{ case List(x,2) =& println(x) }
里面的x就是对匹配到的第一个元素用变量x标记。
3) 通配符模式(wildcard patterns)
通配符用下划线表示:”_” ,可以理解成一个特殊的变量或占位符。
单纯的通配符模式通常在模式匹配的最后一行出现,case _ =&
它可以匹配任何对象,用于处理所有其它匹配不成功的情况。
通配符模式也常和其他模式组合使用:
scala& List(1,2,3) match{ case List(_,_,3) =& println(“ok”) }
上面的 List(_,_,3) 里用了2个通配符表示第一个和第二个元素,这2个元素可以是任意类型
通配符通常用于代表所不关心的部分,它不像变量模式可以后续的逻辑中使用这个变量。
4) 构造器模式(constructor patterns)
这个是真正能体现模式匹配威力的一个模式!
我们来定义一个二叉树:
scala& :paste
// Entering paste mode (ctrl-D to finish)
trait Node //抽象节点
case class TreeNode(v:String, left:Node, right:Node) extends Node //具体的节点实现,有两个子节点
case class Tree(root:TreeNode)
//Tree,构造参数是根节点
// Exiting paste mode, now interpreting.
这样我们构造一个根节点含有2个子节点的数:
scala&val tree = Tree(TreeNode(“root”,TreeNode(“left”,null,null),TreeNode(“right”,null,null)))
如果我们期望一个树的构成是根节点的左子节点值为”left”,右子节点值为”right”并且右子节点没有子节点
那么可以用下面的方式匹配:
scala& tree.root match { case TreeNode(_,TreeNode(“left”,_,_), TreeNode(“right”,null,null)) =& println(“bingo”) }
只要一行代码就可以很清楚的描述,如果用java实现,是不是没这么直观呢?
5) 类型模式(type patterns)
类型模式很简单,就是判断对象是否是某种类型:
scala& “hello” match { case _:String =& println(“ok”) }
跟 isInstanceOf 判断类型的效果一样,需要注意的是scala匹配泛型时要注意,
scala& def foo(a:Any) { a match { case a :List[String] =& println(“ok”); case _ =& } }
如果使用了泛型,它会被擦拭掉,如同java的做法,所以上面的 List[String] 里的String运行时并不能检测
foo(List(“A”))
和 foo(List(2)) 都可以匹配成功。实际上上面的语句编译时就会给出警告,但并不出错。
通常对于泛型直接用通配符替代,上面的写为 case a : List[_] =& …
6) 变量绑定模式 (variable binding patterns)
这个和前边的变量模式有什么不同?看一下代码就清楚了:
依然是上面的TreeNode,如果我们希望匹配到左边节点值为”left”就返回这个节点的话:
scala& tree.root match { case TreeNode(_, leftNode@TreeNode(“left”,_,_), _) =& leftNode }
用@符号绑定 leftNode变量到匹配到的左节点上,只有匹配成功才会绑定
另外解释一下抽取器模式(extractor patterns),一些资料里也会提到这个模式
抽取器是一种实现模式匹配的技术方式,在表现上,抽取器模式与构造器模式一致,都是 case A(e1,e2) =& 这样的形式。
在《Programming in scala》一书中提到 序列模式(sequence patterns),针对所有SeqFactory的子类,它其实就是抽取器模式。
在表达形式上 case List(1,2,3) =& … 或 case Array(“a”,”b”) =& …
看着与构造器模式一模一样(就是背后实现有所不同)
所以在模式的表现形式上,不适合把它划为一类,非要把 序列模式 与构造器模式区分的话,也是从它们背后的实现上,而不是表现上。
另外《Programming in scala》一书中也单独提到 元组模式(tuple patterns), 元组模式本质上也是一个构造器模式。
了解完模式匹配的感念后,我们后续再看一下scala里是怎么实现模式匹配的。
(全文完)
文章来自:
话说模式匹配:什么是模式?王者荣耀匹配模式大改,新地图等你来战,周瑜基本完成
王者荣耀匹配模式大改,新地图等你来战,周瑜基本完成
今天早上王者荣耀的正式服更新了一波,哪知道晚上又要更新体验服了,其实道理很简单,那就是体验服隐藏的新地图被广大玩家发现了,我也给大家发布过几个相关消息,天美官方看到捂不住了,直接给放了出来。
当然,这次新地图肯定不能在排位里面使用,毕竟还有一些bug,怎么办呢?那就在匹配模式用呗,话说体验服的匹配模式已经关了好久了,可能是为了更好统计数据吧,毕竟很多人在匹配模式里面乱玩,只有排位才会认真一些。
大家匹配或者开房间就可以直接进入新地图了,不需要再用什么bug,人人都能参加,看到上图中新风格那几个字没有?这就是新地图的标志,如果有这几个字就是新地图没得跑了。话说体验服好久没开放资格了,应该就在最近了,大家可以时刻关注官网,也可以等我消息。
下面再看看这次更新后唯一改动的英雄:周瑜。
周瑜2技能的火箭落地延迟由0.5秒变成了0.3秒,算是一个不小的增强,为的就是提高他的连招,之后火海就更容易实现了。可以看到,这次的改动很小,那么说明周瑜基本已经调整得差不多了,我们应该可以在最近看到他在正式服出现了,小乔终于不在孤单,不过两个法师同时上场还是有点难啊。
欢迎大家关注和分享,游人馆随时给你们带来王者荣耀的消息心得福利BUG哦,还有当前强势英雄攻略和体验服申请通知等。
本文仅代表作者观点,不代表百度立场。系作者授权百家号发表,未经许可不得转载。
百家号 最近更新:
简介: 游人寻它千百度,不如转入此馆来。
作者最新文章}

我要回帖

更多关于 scala模式匹配语法是 的文章

更多推荐

版权声明:文章内容来源于网络,版权归原作者所有,如有侵权请点击这里与我们联系,我们将及时删除。

点击添加站长微信