【问题标题】:How to pattern match on Map?如何在地图上进行模式匹配?
【发布时间】:2016-02-13 09:57:33
【问题描述】:
val paths @ Array(key_dc_outputDirectory, key_dc_path) = Array("DC_BIN", "DC_PATH")

但下面给出了编译器错误:

val map @ Map(p1, p2) = Map("key1" -> "value1", "key2" -> "value2")

value Map 不是 case 类,也没有 unapply/unapplySeq 成员

避免错误的正确语法是什么?

【问题讨论】:

  • 一般你不能在 Map 上执行这种操作,因为它不能保证元素的顺序。
  • @Chris : cte 是编译时错误。我会确保在以后的帖子中使用完整的形式..

标签: scala


【解决方案1】:

问题显然是Map 没有unapplySeq 方法。拥有它可能没有多大意义,因为您不知道将按什么顺序获取元素。

无论如何,我能得到的最接近的是:

scala> object MapOops {
     |   def apply[K,V](ps: (K,V)*): Map[K,V] =
     |     ps.toMap
     |
     |   def unapplySeq[K,V](m: Map[K,V]): Option[Seq[(K,V)]] =
     |     if(m.isEmpty) None else Some(m.toSeq)
     | }
defined object MapOops

scala> val map@MapOops(p1, p2) = MapOops(1 -> "one", 2 -> "two")
map: Map[Int,String] = Map(1 -> one, 2 -> two)
p1: (Int, String) = (1,one)
p2: (Int, String) = (2,two)

或者,甚至更短:

scala> val map@MapOops(p1, p2) = Map(1 -> "one", 2 -> "two")
map: scala.collection.immutable.Map[Int,String] = Map(1 -> one, 2 -> two)
p1: (Int, String) = (1,one)
p2: (Int, String) = (2,two)

用这样的东西拉皮条Map是没有意义的:

implicit class MapOops[K,V](val m: Map[K,V]) extends AnyVal

因为当您在模式匹配中使用 Map 时,不会发生隐式转换,因为未请求/隐含 MapOops 类型。

例如:case Map(...)val Map(...) 将需要类型 Map,而不是 MapOops,因此不会发生隐式转换并且不会找到 unapplySeq 方法。如果您显式使用MapOops,则无需进行隐式转换。

如果您经常使用这种模式,那么您可能会发现这个帮助程序类很有用,否则更明智的解决方案是像 @jwvh 的回答那样进行额外的转换。

【讨论】:

    猜你喜欢
    • 2012-12-02
    • 2021-06-13
    • 1970-01-01
    • 2021-04-08
    • 1970-01-01
    • 2015-04-02
    • 2022-01-05
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多