scala 模式匹配
Posted triumph丶xs
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了scala 模式匹配相关的知识,希望对你有一定的参考价值。
模式匹配
TODO - 模式匹配 - 匹配规则
1.类似于java中switch
2.当数据满足某一个分支时,执行完毕后,就直接跳出
3.case _ 分支类似于default语言, 分支匹配其实就是顺序匹配
4.如果数据没有匹配任何规则,会发生错误
模式匹配语法中,采用match关键字声明,每个分支采用case关键字进行声明,当需要匹配时,会从第一个case分支开始,如果匹配成功,那么执行对应的逻辑代码,
如果匹配不成功,继续执行下一个分支进行判断。如果所有case都不匹配,那么会执行case _分支,类似于Java中default语句。如果不存在case _分支,那么会发生错误。
1 匹配类型
类型前增加变量名称,这个变量就是将数据转换成指定类型的变量
如果想要使用下划线代表的数据,可以给下划线起名来使用(比如 somthing 代替_)
scala中类型匹配时,是不考虑泛型的,但是Array类型是特殊的。(比如List[_]匹配的list集合无论里面的类型是多少)
def describe(x: Any) = x match {
case i : Int => i + 10
case s : String => "String hello"
case m: List[_] => "List"
case c: Array[Int] => "Array[Int]"
case someThing => "something else " + someThing
}
// Array[Int], 这里的Int不是真正的泛型
// java => String[]
// scala => Array[String]
println(describe(List("1", "2", "3")))
2 匹配数组
判定给定的数组的规则
for (arr <- Array(Array(0), Array(1, 0), Array(0, 1, 0), Array(1, 1, 0), Array(1, 1, 0, 1), Array("hello", 90))) { // 对一个数组集合进行遍历
val result = arr match {
case Array(0) => "0" //匹配Array(0) 这个数组
case Array(x, y) => x + "," + y //匹配有两个元素的数组,然后将将元素值赋给对应的x,y
case Array(0, _*) => "以0开头的数组" //匹配以0开头和数组
case _ => "something else"
}
println("result = " + result)
}
3 匹配列表
for (list <- Array(List(0), List(1, 0), List(0, 0, 0), List(1, 0, 0), List(88))) {
val result = list match {
case List(0) => "0" //匹配List(0)
case List(x, y) => x + "," + y //匹配有两个元素的List
case List(0, _*) => "0 ..."
case _ => "something else"
}
println(result)
}
val list: List[Int] = List(1, 2, 5, 6, 7)
list match {
case first :: second :: rest => println(first + "-" + second + "-" + rest)
case _ => println("something else")
}
::对于这个符号就是追加的意思 上述就是能否分成三部分 1-2-List(5, 6, 7)
对于 val list: List[Int] = List(1)
println(list.head) //1
println(list1.tail) //list()
//1::Nil
println(list1.init) //list()
println(list1.last)//1
//List().append(1)
4 匹配元组
for (tuple <- Array((0, 1), (1, 0), (1, 1), (1, 0, 2))) {
val result = tuple match {
case (0, _) => "0 ..." //是第一个元素是0的元组
case (y, 0) => "" + y + "0" // 匹配后一个元素是0的对偶元组
case (a, b) => "" + a + " " + b
case _ => "something else" //默认
}
println(result)
}
val map = Map(
("a", 1), ("b", 2), ("c", 3)
)
for ( (k, 2) <- map ) {
println( k )
}
for((k,v)<- map){
println(k+"="+v)
}
1.匹配数据时,需要使用case关键字
2.case分支可能存在多个,那么需要将map的小括号换成大括号
//需求 : (("河北", "鞋"), 10) =>(河北,(鞋,10))
val list = List(
(("河北", "鞋"), 10),
(("河北", "衣服"), 20),
(("河北", "电脑"), 15),
)
val tuples: List[(String, (String, Int))] = list.map(
(t) => { //这个t外面的括号代表的是参数列表的括号
((t._1._1), (t._1._2, t._2))
}
)
println(tuples)
val list1 = list.map {
case ((prv, item), cnt) => {
(prv, (item, cnt * 2))
}
}
println(list1)
5 匹配对象
拿到对象:apply : Attribute => Object比对时需要 unapply : Object => Attribute
def main(args: Array[String]): Unit = {
// TODO - 模式匹配 - 匹配规则
// 匹配对象
// apply : Attribute => Object
val user = getUser()
// unapply : Object => Attribute
user match {
case User("zhangsan",40) => println("用户为张三")
case _ => println("什么也不是")
}
}
class User {
var name:String = _
var age:Int = _
}
object User {
// Object => Attribute
def unapply(user: User): Option[(String, Int)] = {
Option( (user.name, user.age) )
}
// Attribute => Object
def apply( name : String, age:Int ) = {
val user = new User()
user.name = name
user.age = age
user
}
}
def getUser() = {
User("zhangsan", 30)
}
}
5 样例类
对匹配对象的一种简化,省去了大量的代码,如果在类的前面的增加case关键字,这个类专门用于模式匹配,称之为样例类
在编译时,会自动生成大量的方法
1. 样例类会自动实现可序列化接口
2. 样例类的构造参数直接能够作为属性使用,但是不能修改,如果想要修改,需要将参数使用var声明
3. 增加和重写了大量的方法 如apply、unapply、toString、equals、hashCode和copy。
4. 样例类自动生成伴生对象,而且其中自动声明了apply,unapply
5. 构造器中的每一个参数都成为val,除非它被显式地声明为var(不建议这样做)
def main(args: Array[String]): Unit = {
// TODO - 模式匹配 - 匹配规则
val user = getUser()
user.name = "lisi"
user match {
case User("zhangsan",40) => println("用户为张三")
case _ => println("什么也不是")
}
}
case class User(var name:String, age:Int)
def getUser() = {
User("zhangsan", 40)
}
6 偏函数
所谓的偏函数,其实就是对集合中符合条件的数据进行处理的函数
全量函数 :函数进行处理时必须对所有的数据进行处理。map只支持全量函数操作 flatmap
def main(args: Array[String]): Unit = {
val list = List(1,2,3,4) //map只支持全量函数操作 即使不满足也要处理 不满足就是没有值 UNIT
val list1: List[AnyVal] = list.map(
num => {
if (num % 2 != 0) {
num * 2
}
}
)
println(list1)
}
List(2, (), 6, ())
需求:将该List(1,2,3,4,5,6,"test")中的Int类型的元素加一,并去掉字符串
1.不使用偏函数
val newlist : List[Any] = list.filter(_.isInstanceOf[Int])
val newlist1 = newlist.map(_.asInstanceOf[Int] + 1)
println(newlist1)
2.模式匹配
val list1 = list.map {
case i : Int => {
i + 1
}
case other => other
}.filter(_.isInstanceOf[Int])
println(list1)
3.偏函数
def main(args: Array[String]): Unit = {
// TODO - 模式匹配 - 偏函数
val list : List[Any] = List(1,2,3,4,5,6,"test")
val list1 = list.collect{
case i : Int => i + 1
}
println(list1)
}
以上是关于scala 模式匹配的主要内容,如果未能解决你的问题,请参考以下文章