【Scala】Scala ~ 基本編 / パターンマッチング ~

■ はじめに

Scala の パターンマッチング が強力って話が業務中にでてきたので
調べて、まとめる

目次

【0】パターンマッチング
【1】定数パターン - 定数でのマッチング
【2】条件束縛パターン - ガード条件(if)でのマッチング
【3】関数として定義
【4】データ型でのマッチング
【5】固定長シーケンスパターン - 配列数でのマッチング
【6】ケースクラスでのマッチング

【0】パターンマッチング

https://docs.scala-lang.org/ja/tour/pattern-matching.html

* パターンに照合するための仕組み
* マッチに成功すれば、一つの値をその構成要素のパーツに分解することもできる
* Javaのswitch文の強化バージョン
パターン名 case式の例
ワイルドカードパターン case _
定数パターン case 定数
変数パターン case 変数
変数束縛パターン case パターン変数 @ (束縛条件)
条件束縛パターン case パターン変数 if 束縛条件
型付きパターン case X: データ型
固定長シーケンスパターン case List(X, X, X)
任意長パターン case List(X, _X)
タプルパターン case (X, X)
コンストラクタパターン case Some(引数)
抽出子パターン case 抽出子(引数)

【1】定数パターン - 定数でのマッチング

例1:Hello world

object DemoMain {
  def main(args: Array[String]): Unit = {
    // Change me!
    val testValue = 0

    // ★ここに注目★
    val result = testValue match {
      case 0 => "NG"
      case 100 => "OK"
      case _ => "Not 0 or 100"
    }

    println(s"result: ${result}")
  }
}

例2:OR(|)

object Hello {
  def main(args: Array[String]): Unit = {
    // Change me!
    val testValue = 3

    val result = testValue match {
      // ★ここに注目★
      case 0 | 1 | 2  => "0 or 1 or 2"
      case 3 | 4 | 5 => "3 or 4 or 5"
      case _ => "Not 1 to 5"
    }

    println(s"result: ${result}")
  }
}

【2】条件束縛パターン - ガード条件(if)でのマッチング

object  Hello {
  def main(args: Array[String]): Unit = {
    val str = "1,2,3,4,5,"
    val results = str.split(",")

    // ★別解は、「【4】データ型でのマッチング」の「例2:配列数」を参照
    results.size match {
      // ★注目
      case size if size >= 2 =>
        val x1 = results(0)
        val x2 = results(1)
        println(s"${x1} - ${x2}") // 1 - 2
        // case 中の変数 size もそのまま使える
        val x3 = if (size != 5) "XX" else results(4)
        println(s"${x3}") // 5
      case _ => println("data must be more than 2")
    }
  }
}

【3】関数として定義

object DemoMain {

  def matching(testValue: Int): String = testValue match {
    case 0 => "NG"
    case 100 => "OK"
    case _ => "Not 0 or 100"
  }

  def main(args: Array[String]): Unit = {
    val testValue = 100
    val result = matching(testValue)
    println(s"result: ${result}")
  }
}

【4】データ型でのマッチング

例1:データ型

object Hello {
  def main(args: Array[String]): Unit = {
    val testValues = List(1, "Mike", true, 12.12, Array("AA", "BB"))
    for (value <- testValues) {
      value match {
        case id: Integer => println(s"id=${id}")
        case name: String => println(s"name=${name}")
        case isMale: Boolean => println(s"isMale?=${isMale}")
        case array: Array[String] => println(s"array.length=${array.length}")
        case _ => println(s"value=${value}")
      }
    }
  }
}

【5】固定長シーケンスパターン - 配列数でのマッチング

例1:配列数

object  Hello {
  def main(args: Array[String]): Unit = {
    val str = "Hello,World,Mike"

      str.split(",") match {
        case Array(greet) => println(s"${greet}!")
        case Array(greet,place) => println(s"${greet} ${place}!!")
        case Array(greet,place,name) => println(s"${greet} ${place}, ${name}!!")
        case _ => println("Not supported")
      }
  }
}

【6】ケースクラスでのマッチング

abstract class Week

case class Sunday() extends Week
case class Monday() extends Week
case class Tuesday() extends Week
case class Wednesday() extends Week
case class Thursday() extends Week
case class Friday() extends Week
case class Saturday() extends Week

object DemoMain {
  def sayTodaysWeek(week: Week): String = {
    week match {
      case Saturday() => "Today is Saturday"
      case Sunday() => "Today is Sunday"
      case _ => "Today is boring day..."
    }
  }

  def main(args: Array[String]): Unit = {
    println(sayTodaysWeek(new Sunday)) 
  }
}

参考文献

https://qiita.com/f81@github/items/aa46c248a38a171ed955
https://www.tohoho-web.com/ex/scala.html#match

関連記事

Scala ~ 環境構築編 ~
https://dk521123.hatenablog.com/entry/2023/03/10/193805
Scala ~ 入門編 ~
https://dk521123.hatenablog.com/entry/2023/03/12/184331
Scala ~ 基本編 / 文字列 ~
https://dk521123.hatenablog.com/entry/2023/01/07/000000
Scala ~ 基本編 / 正規表現
https://dk521123.hatenablog.com/entry/2023/03/18/034704
Scala ~ 基本編 / Either型 ~
https://dk521123.hatenablog.com/entry/2023/08/02/132315
ScalaEnum
https://dk521123.hatenablog.com/entry/2023/01/05/000000