マップに対するパターンマッチ
マップに対するパターンマッチに使える extractor が標準では用意されていないようだし、ぐぐってみてもそれっぽい例が見つからないので、書いてみた。
特定のキー群に対する値を取り出したい場合
class MapValues[A](all: Boolean, keys: A*) { def unapplySeq[B](map: Map[A, B]): Option[Seq[B]] = { if (all && keys.toSet != map.keySet) None else try Some(keys.map(map)) catch { case _: NoSuchElementException => None } } }
val map = Map(1 -> "January", 2 -> "February", 3 -> "March") // 一部のキー以外は無視したい場合 val false_1_2 = new MapValues(false, 1, 2) val false_1_2(jan, feb) = map // jan = January; feb = February val false_3 = new MapValues(false, 3) val false_3(mar) = map // mar = March // 全てのキーを扱いたい場合 val true_3 = new MapValues(true, 3) val true_3(mar) = map // MatchError val true_3_2_1 = new MapValues(true, 3, 2, 1) val true_3_2_1(mar, feb, jan) = map // mar = March; feb = February; jan = January
全てのキーと値を取り出したい場合(キーの昇順に)
object MapElems { def unapplySeq[A, B](map: Map[A, B])(implicit ord: Ordering[A]): Option[Seq[(A, B)]] = { Some(map.toSeq.sortBy { case (k, v) => k } (ord)) } }
val map = Map(1 -> "January", 2 -> "February", 3 -> "March") val MapElems((one, jan), (two, feb), (three, mar)) = map // one = 1; jan = January; two = 2; feb = February; three = 3; mar = March
全てのキーと値を取り出したい場合(キーの順序を指定して)
class MapElems[A](ord: Ordering[A]) { def unapplySeq[B](map: Map[A, B]): Option[Seq[(A, B)]] = { MapElems.unapplySeq(map)(ord) } }
val map = Map(1 -> "January", 2 -> "February", 3 -> "March") val descending = new MapElems(Ordering[Int].reverse) // Int の降順で val descending((three, mar), (two, feb), (one, jan)) = map // three = 3; mar = March; two = 2; feb = February; one = 1; jan = January