一.变量声明中的模式匹配
现在有一个数组Array(1,2,3,4),定义三个变量,它们的值分别是数组中的第1,2,3个元素的值。
基础实现:
val arr = Array(1,2,3,4,5)
val x = arr(0)
val y = arr(1)
val z = arr(2)
println(x,y,z)
使用模式匹配的实现
val arr = Array(1,2,3,4)
val Array(x,y,z,_*) = arr
println(x,y,z)
其中: _*表示多个其他的元素值。
package matchcase
// match case 的用法
// (6)变量声明中的模式匹配
object matchcase06 {
def main(args: Array[String]): Unit = {
val arr = Array(1,2,3,4,5)
// 定义三个变量,分别设置初始值为arr的前三个元素的值
var a = arr(0)
var b = arr(1)
var c = arr(2)
println("a = " + a + " b = " + b + " c = " + c)
// 使用模式匹配,将arr的前三个元素分别赋值给a,b,c
// _* 占位符,表示多的部分放在这儿
val Array(x,y,z,_*) = arr
println("x = " + x + " y = " + y + " z = " + z)
}
}
package matchcase
/*
知识点:守卫
value match {
case 模式 if 条件 => 执行的事情
*/
object matchcase07 {
def main(args: Array[String]): Unit = {
val a = 11
a match {
case x: Int if a > 10 => println("a是大于10的Int")
case _ => println("a is not Int")
}
}
}
二.守卫语句的格式
守卫语句紧跟在case模式之后,通过if关键字引入,格式如下:
value match {
case pattern if guardCondition => result
// 其他case语句...
}
package matchcase
/*
知识点:守卫
value match {
case 模式 if 条件 => 执行的事情
*/
object matchcase07 {
def main(args: Array[String]): Unit = {
val a = 11
a match {
case x: Int if a > 10 => println("a是大于10的Int")
case _ => println("a is not Int")
}
}
}
其中,value是要进行匹配的值,pattern是匹配模式,guardCondition是守卫条件(一个布尔表达式),result是当该case分支匹配成功时返回的结果。
具体如下:
从控制台读入一个数字a,使用(StdIn.readInt)
如果a>=0并且a<=3,打印[0-3]
如果 a>=4并且a<=8,打印[4-8]
否则:打印未匹配
【案例1】
在1-100内,如果数字>10并且是偶数,就输出:"是大于10的偶数",如果数字是>80并且是奇数,就输出:"是大于80的奇数"。
思路:在循环内部使用match case,并使用守卫语句。
for (i <- 1 to 100) {
i match {
case x if x > 10 && x % 2 == 0 => println(s"$i 是大于10的偶数")
case x if x > 80 && x % 2 != 0 => println(s"$i 是大于80的奇数")
case _ =>
}
}
三.匹配for表达式
从Map中打印所有年龄为1971的创业者的信息。
val m1 = Map(
"马云 - 阿里巴巴" -> 1964, "马化腾 - 腾讯" -> 1971,
"李彦宏 - 百度" -> 1968, "雷军 - 小米" -> 1969,
"丁磊 - 网易" -> 1971, "张一鸣 - 字节跳动" -> 1983,
"刘强东 - 京东" -> 1974, "程维 - 滴滴" -> 1983,
"王兴 - 美团" -> 1979, "周鸿祎 - 360" -> 1970,
"黄峥 - 拼多多" -> 1980, "李想 - 理想汽车" -> 1981,
"何小鹏 - 小鹏汽车" -> 1977, "贾跃亭 - 乐视" -> 1973,
"陈天桥 - 盛大网络" -> 1973, "周源 - 知乎" -> 1980,
"王小川 - 搜狗" -> 1978
)
// 请补充代码,输出: 马化腾 - 腾讯, 丁磊 - 网易
//
方式1:使用 for + if守卫
for((key,year) <- m1 if year==1971){
println(key, year)
}
方式2:使用模式匹配
for((key,1971) <- m1){
println(key, 1971)
}
四.案例-判断星座
目标任务,编写一个函数,参数是月份和日期,返回值是当前的星座。
例如,getZodiac(3, 24) 返回白羊座 。
白羊座是3月21日 ~ 4月19日
先匹配月份,然后使用守卫功能,判断日期是否满足条件。
object Zodiac {
def getZodiac(month: Int, day: Int): String = {
(month, day) match {
case (1, d) if d >= 20 => "水瓶座"
case (12, d) if d >= 22 => "摩羯座"
case (1, d) if d <= 19 => "摩羯座"
case _ => "无效日期"
}
}
def main(args: Array[String]): Unit = {
println(getZodiac(3, 21)) // 输出: 白羊座
println(getZodiac(12, 25)) // 输出: 摩羯座
}
可对比介绍使用if else if 来实现的效果。
package matchcase
/*
写一个函数,参数有两个,一个是月份,一个是日期。返回值是对应的星座
1月20日到2月18日:水瓶座
*/
object matchcase08 {
def getZodiac(month:Int, day:Int):String = {
month match {
case 1 if day >= 20 => "水瓶座"//月份是1,并且日期是>=20的
case 2 if day <= 18 => "水瓶座"//月份是2,并且日期是<=18的
case 2 if day >= 19 => "双鱼座"//月份是2,并且日期是>=19的
case 3 if day <= 20 => "双鱼座"//月份是3,并且日期是<=20的
case 3 if day >= 21 => "白羊座"//月份是3,并且日期是>=21的
case 4 if day <= 19 => "白羊座"//月份是4,并且日期是<=19的
case 4 if day >= 20 => "金牛座"//月份是4,并且日期是>=20的
case 5 if day <= 20 => "金牛座"//月份是5,并且日期是<=20的
case 5 if day >= 21 => "双子座"//月份是5,并且日期是>=21的
case 6 if day <= 21 => "双子座"//月份是6,并且日期是<=21的
case 6 if day >= 22 => "巨蟹座"//月份是6,并且日期是>=22的
case 7 if day <= 22 => "巨蟹座"//月份是7,并且日期是<=22的
case 7 if day >= 23 => "狮子座"//月份是7,并且日期是>=23的
case 8 if day <= 22 => "狮子座"//月份是8,并且日期是<=22的
case 8 if day >= 23 => "处女座"//月份是8,并且日期是>=23的
case 9 if day <= 22 => "处女座"//月份是9,并且日期是<=22的
case 9 if day >= 23 => "天秤座"//月份是9,并且日期是>=23的
case 10 if day <= 23 => "天秤座"//月份是10,并且日期是<=23的
case 10 if day >= 24 => "天蝎座"//月份是10,并且日期是>=24的
case 11 if day <= 22 => "天蝎座"//月份是11,并且日期是<=22的
case 11 if day >= 23 => "射手座"//月份是11,并且日期是>=23的
case 12 if day <= 21 => "射手座"//月份是12,并且日期是<=21的
case 12 if day >= 22 => "摩羯座"//月份是12,并且日期是>=22的
case 1 if day <= 19 => "摩羯座"//月份是1,并且日期是<=19的
case _ =>"未知"
}
}
def main(args: Array[String]): Unit = {
println(getZodiac(1,19))//水瓶座
println(getZodiac(1,21))//水瓶座
}
}