大数据之Scala 模式匹配 完整使用(第八章)

导读:本篇文章讲解 大数据之Scala 模式匹配 完整使用(第八章),希望对大家有帮助,欢迎收藏,转发!站点地址:www.bmabk.com

一、模式匹配

一、基本语法

模式匹配语法中,采用 match 关键字声明,每个分支采用 case 关键字进行声明,当需
要匹配时,会从第一个 case 分支开始,如果匹配成功,那么执行对应的逻辑代码,如果匹配不成功,继续执行下一个分支进行判断。如果所有 case 都不匹配,那么会执行 case _分支,类似于 Java 中 default 语句

1、实操

package chapter08

/**
 * 模式匹配
 */
object Test01_PatternMatchBase {
  def main(args: Array[String]): Unit = {
    //1、基本定义语法
    val x: Int = 2
    val y: String = x match {
      case 1 => "one"
      case 2 => "two"
      case 3 => "three"
      case _ => "other"
    }
    println(y)


    //2、实例:用模式匹配实现简单二元运算
    val a = 25
    val b = 13

    def matchDualOp(op: Char) = op match {
      case '+' => a + b
      case '-' => a - b
      case '*' => a * b
      case '/' => a / b
      case _ => -1

      //如果一个引用类型、和值类型肯定返回值为Any
    }

    println(matchDualOp('+'))
    println(matchDualOp('/'))
    println(matchDualOp('\\'))

    def getCount(op: String) = op match {
      case "+" => a + b
      case _ => -2
    }

    println(getCount("+"))


    //模式守卫
    println("---------模式守卫---------------")
    //求一个整数的绝对值
    def abs(num: Int): Int = {
      num match {
        case i if i >= 0 => i
        case i if i < 0 => i
      }
    }

    println(abs(67))
    println(abs(0))
    println(abs(-24))


  }
}

2、说明

(1)如果所有 case 都不匹配,那么会执行 case _ 分支,类似于 Java 中 default 语句,
若此时没有 case _ 分支,那么会抛出 MatchError。
(2)每个 case 中,不需要使用 break 语句,自动中断 case。
(3)match case 语句可以匹配任何类型,而不只是字面量。
(4)=> 后面的代码块,直到下一个 case 语句之前的代码是作为一个整体执行,可以
使用{}括起来,也可以不括。

二、匹配常量

1)说明

Scala 中,模式匹配可以匹配所有的字面量,包括字符串,字符,数字,布尔值等等。

2)实操

package chapte

/**
 * 匹配常量
 */
object Test02_MatchTypes {
  def main(args: Array[String]): Unit = {
    def describeConst(x: Any): String = x match {
      case 1 => "Int One"
      case "hello" => "String hello"
      case true => "Boolean True"
      case '+' => "Char +"
      case abc => ""
    }

    println(describeConst("hello"))
    println(describeConst('+'))
    println(describeConst(0.3))

    //匹配类型
    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)))


    def getName(x: Any): String = x match {
      case 1 => "张"
      case 2 => "黄"

    }

    println(getName(2))
  }
}

三、匹配类型

1)说明

需要进行类型判断时,可以使用前文所学的 isInstanceOf[T]和 asInstanceOf[T],也可使
用模式匹配实现同样的功能。

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)))

四、模式守卫

1)说明

如果想要表达匹配某个范围的数据,就需要在模式匹配中增加条件守卫。

2)案例实操

    //模式守卫
    println("---------模式守卫---------------")
    //求一个整数的绝对值
    def abs(num: Int): Int = {
      num match {
        case i if i >= 0 => i
        case i if i < 0 => i
      }
    }

    println(abs(67))
    println(abs(0))
    println(abs(-24))

五、匹配数组

1)说明

scala 模式匹配可以对集合进行精确的匹配,例如匹配只有两个元素的、且第一个元素
为 0 的数组。

2)案例实操

 /**
     * 1、测试代码
     * 匹配数组
     * 常量类型 匹配
     * 0
     * (1, 0)
     * 以零开头的数组
     * 中间为1的三元数组
     * something else
     * something else
     *
     * @return
     */
    for (arr <- List(
      Array(0),
      Array(1, 0),
      Array(0, 1, 0),
      Array(1, 1, 0),
      Array(2, 3, 7, 15),
      Array("hello", 20, 30),
    )) {
      val result = arr match {
        case Array(0) => "0"
        case Array(1, 0) => "(1, 0)"
        case Array(x, y) => "Array: " + x + "," + y //匹配两元素数组
        case Array(0, _*) => "以零开头的数组" //匹配两元素数组
        case Array(x, 1, z) => "中间为1的三元数组"
        case _ => "something else"
      }
      println(result)
    }

六、匹配列表

 println("........匹配列表")
    for (list <- List(
      List(0),
      List(1, 0),
      List(0, 0, 0),
      List(1, 1, 0),
      List(88),
      List("hello"),
    )) {
      val result = 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)
    }


    //方式二、
    var list = List(1, 2, 5, 7, 24)
    list match {
      case first :: second :: rest =>
        println(s"first: $first ,second $second, rest $rest ")
      case _ => println("something else")

    }

七、匹配元组

    println("......匹配元组............")
    //匹配元组
    for (tuple <- List(
      (0, 1),
      (0, 0),
      (0, 1, 0),
      (0, 1, 1),
      (1, 23, 56),
      ("hello", true, 0.5),
    )) {
      tuple match {
        case (a, b) => "" + a + "," + b
        case (0, _) => "(0,_)"
        case (a, 1, _) => "(a,1_)" + a
        case _ => "something else"
      }
    }

七、变量声明

package chapter08

/**
 * 变量声明
 */
object Test03_MatchTupleExtend {

  def main(args: Array[String]): Unit = {
    //在变量声明时匹配
    val (x, y) = (10, "hello")
    println(s"$x , $y")

    println("-------------------------")
    val List(first, second, _*) = List(23, 159, 78)
    println(s"first $first, second $second")

    println("-------------------------")
    val fir :: sec :: rest = List(23, 15, 9, 8)
    println(s"first $fir, sec $sec rest $rest")

  }
}

八、for推导式中变量

package chapter08

/**
 * 变量声明
 */
object Test03_MatchTupleExtend {

  def main(args: Array[String]): Unit = {
    //在变量声明时匹配
    val (x, y) = (10, "hello")
    println(s"$x , $y")

    println("-------------------------")
    val List(first, second, _*) = List(23, 159, 78)
    println(s"first $first, second $second")

    println("-------------------------")
    val fir :: sec :: rest = List(23, 15, 9, 8)
    println(s"first $fir, sec $sec rest $rest")

    println("-------------------------")
    //2、for 推导式中进行模式匹配
    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27))

    //2.1原本的遍历方式
    for (elem <- list) {
      println(elem._1 + " " + elem._2)
    }

    println("-------------------------")
    //2.2 将List的元素直接定义为元组,对变量赋值
    for ((elem, count) <- list) {
      println(elem, count)
    }
    
    println("-------------------------")
    //2.3 可以不考虑某个位置的变量,只遍历key或者value
    for ((word, _) <- list) {
      println(word)
    }

    println("-------------------------")
    //2.4 可以指定某个位置的值必须是多少
    for (("a", count) <- list) {
      println(count)
    }

  }
}

九、模式匹配对象的值

package chapter08

/**
 * 匹配对象的值
 *
 */
object Test04_MatchObject {
  def main(args: Array[String]): Unit = {

    val student = new Student("alice", 18)

    val str = student match {
      case Student("alice", 18) => "Alice,18"
      case _ => "Else"
    }

    println(str)
  }
}

//定义类
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))
    }
  }
}

十、定义样例类

package chapter08

/**
 * 定义样例类
 * 代替了上面的
 */
object Test05_MatchCaseClass {
  def main(args: Array[String]): Unit = {
    val student = Student1("alice", 18)

    val str = student match {
      case Student1("alice", 18) => "alice 18"
      case _ => "ELSE"
    }

    println(str)

  }
}

//定义样例类

case class Student1(name: String, age: Int)

十一、偏函数

偏函数也是函数的一种,通过偏函数我们可以方便的对输入参数做更精确的检查。例如 该偏函数的输入类型为
List[Int],而我们需要的是第一个元素是 0 的集合,这就是通过模式 匹配实现的。

package chapter08

/**
 * 偏函数
 */
object Test06_PartialFunction {
  def main(args: Array[String]): Unit = {

    val list: List[(String, Int)] = List(("a", 12), ("b", 35), ("c", 27), ("a", 13))

    //1、Map转换,实现Key不变 value 2倍
    val newList = list.map(tuple => (tuple._1, tuple._2 * 2))


    //2、用模式匹配对元组元素赋值,实现功能
    val tuples = list.map(
      tuple => {
        tuple match {
          case (word, count) => (word, count * 2)
        }
      }
    )


    val newList3 = list.map {
      case (word, count) => (word, count * 2)
    }


    println(newList)
    println(tuples)
    println(newList3)


    //偏函数的应用吗,求绝对值
    //对输入数据分为不同的情形,正、负、0

    val positiveAbs: PartialFunction[Int, Int] = {
      case x if x > 0 => x
    }

    val negativeAbs: PartialFunction[Int, Int] = {
      case x if x < 0 => -x
    }

    val zeroAbs: PartialFunction[Int, Int] = {
      case 0 => 0
    }

    def abs(x: Int): Int = (positiveAbs orElse negativeAbs orElse zeroAbs) (x)

    println(abs(-67))
    println(abs(35))
    println(abs(0))
  }
}

版权声明:本文内容由互联网用户自发贡献,该文观点仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 举报,一经查实,本站将立刻删除。

文章由极客之音整理,本文链接:https://www.bmabk.com/index.php/post/15449.html

(0)
小半的头像小半

相关推荐

极客之音——专业性很强的中文编程技术网站,欢迎收藏到浏览器,订阅我们!