如何匹配打字的嵌套地图?

时间:2015-12-11 10:55:59

标签: scala pattern-matching

我有Map[String, Any],例如来自JSON反序列化器:

def map: Map[String, Any] = Map("hello" -> Map("world" -> "value"))

我希望获得嵌套密钥Option的{​​{1}}:

"hello"."world"

但是这个解决方案不是类型安全的 - 它会发出警告'未经检查,因为它被擦除'并且在错误的值类型上会失败。

如何以安全的方式实现这一目标?如果嵌套对象是包含键val value = map.get("hello").flatMap { case m: Map[String, String] => m.get("value") case _ => None } assert(value == Some("value")) "world"的有效/兼容类型的地图,则返回值?

编辑:这不是NoneManifest[]。我知道确切的Map类型在运行时是不可访问的,但是想要以某种方式更好地解决投射键(这是安全的btw吗?)并对值进行TypeTag[]

4 个答案:

答案 0 :(得分:2)

对于这种情况

val value = map.get("hello").flatMap {
  case m: Map[String @unchecked, _] => m.get("value")
  case _ => None
}

是安全的:如果m的密钥类型不是Stringget将只返回None!您可以做的另一件事是使用实际的JSON AST,因为您

}

Map[String, Any]

现在,您可以轻松定义您想要的内容而无需强制转换,甚至可能不安全:

sealed trait JValue
...
case class JMap(underlying: Map[String, JValue]) {
  def get(key: String) = underlying.get(key)
}

答案 1 :(得分:1)

仅仅是出于理论原因。可以这样做:

 val value = map.get("hello").map {
    case m: Map[_, _] => m collectFirst {case ("world", v) => v}
    case _ => None
  }

但它过于复杂,而且不实用。更糟糕的是,当在O(1)中搜索地图时,它会搜索O(n)中的内部Map

我认为你不能以任何其他方式做到这一点,我也不会推荐这个。虽然解决方案可能使用相同的想法,但更简单 - 不幸的是我想不出任何

答案 2 :(得分:0)

有一种优雅的方法可以解决这个问题。

1)声明TypeCase

import shapeless._
val mapType: TypeCase[Map[String, String]] = TypeCase[Map[String, String]]

2)在模式匹配上使用它以避免类型擦除

val value = Map("hello" -> Map("world" -> "value")).get("hello").flatMap {
  case mapType(m) => m.get("world")
  case _ => None
} 
assert(value == Some("value"))

答案 3 :(得分:-1)

试试这个:

google.maps.event.addDomListener( window, 'load', function()