【问题标题】:How to get value from nested map of type AnyRef如何从 AnyRef 类型的嵌套映射中获取值
【发布时间】:2019-03-29 06:39:15
【问题描述】:

所以我有一个类型的地图

Map[String, AnyRef]

当我通过println 打印这张地图时,它会给出以下输出

Map(revision -> 
 Map(comment -> "string1", 
     contributor -> Map(id -> "int1", username -> "string2"), 
     format -> "string3", 
     id -> "int2", 
     minor -> None, 
     model -> "string4", 
     parentid -> "int3", 
     sha1 -> "string5", 
     text -> Map(_VALUE -> "VALUE-THAT-I-WANT-TO-GET", 
     space -> ""), 
     timestamp -> Timestamp, 
     title -> "string6"))

现在,正如您在地图中看到的那样,我想获取键 _VALUE 的值。

我尝试从this 答案中解释的嵌套地图中获取它,但它不起作用可能是因为它的类型为AnyRef
在简单的字符串变量中获取它的最佳方法是什么?

如果地图可读性不够,我很抱歉,如果您以更好的方式编辑它,我会接受。但它已完整发布以明确问题。

【问题讨论】:

    标签: scala scala-2.11


    【解决方案1】:

    假设您有一位同事会生成这样的代码。当然,那个人会因为不称职而被解雇。唉,在它可以被重写为适当的 Scala 之前,你会被困在使用它的任务中。

    这是你可以做的一件事。它编译时带有警告,但似乎产生了所需的结果。

    def extract(m :collection.Map[String,AnyRef], key :String) :Option[String] = {
      if (m.isDefinedAt(key)) Some(m(key).toString)
      else {
        val res = m.values
                   .collect{case ma:Map[String,AnyRef] => extract(ma,key)}
                   .dropWhile(_.isEmpty)
        if (res.isEmpty) None else res.head
      }
    }
    
    extract(badMap, "_VALUE") //res0: Option[String] = Some(VALUE-THAT-I-WANT-TO-GET)
    extract(badMap, "_XALUE") //res1: Option[String] = None
    

    【讨论】:

    • 感谢您的回复,当我尝试调用此函数时,它会产生错误type mismatch=> found: scala.collection.Map[String,AnyRef] || required: scala.collection.immutable.Map[String, _]
    • @saadi;代码已调整。
    • 像魅力一样工作,谢谢。您还应该检查@jgoday 的答案,它可以在没有警告的情况下工作,但我猜它不太通用。
    【解决方案2】:

    您可以包装您的地图(别名 anymap)来定义一个 getAs[T] 方法,该方法返回一个 Option 等等...

    import scala.reflect.ClassTag
    
    val m: Map[String, AnyRef] = Map("a" -> Map("b" -> Map("c" -> "d")))
    
    type AnyMap = Map[String, AnyRef]
    
    implicit class AnyMapWrapper(m: AnyMap) {
        def getAs[T](key: String)(implicit ev: ClassTag[T]): Option[T] = m(key) match {
            case i: T => Some(i.asInstanceOf[T])
          case _ => None
      }
    }
    
    println {
        m.getAs[AnyMap]("a").flatMap(_.getAs[AnyMap]("b")).map(_("c"))
    }
    
    println {
      for {
        a <- m.getAs[AnyMap]("a")
        b <- a.getAs[AnyMap]("b")
      } yield b("c")
    }
    

    【讨论】:

    • 感谢您的回复。当我尝试执行val m: Map[String, AnyRef] = myMap 时,它会显示Expression of type scala.collection.Map[scala.Predef.String, AnyRef] does not conform to type scala.Predef.Map[scala.Predef.String, AnyRef]。我现在能做什么?
    • scastie.scala-lang.org/jgoday/J6e4R1h9SEeSWFn6rRytAA 也许你想导入 scala.collection.Map (我认为 predef Map 是 scala.collection.immutable.Map )
    • 工作就像一个魅力,谢谢,但我将不得不接受@jwvh 的回答,因为它对我没有经验的自己来说更通用、可读和易于理解。你的作品没有任何警告。
    【解决方案3】:

    详细(但明确)的版本可能是:

    yourMap.get("revision") collect {
      case Some(otherMap: Map[String, AnyRef]) => otherMap.get("text")
    } collect {
      case Some(yetAnotherMap: Map[String, AnyRef]) => yetAnotherMap.get("_VALUE")
    }
    

    【讨论】:

      猜你喜欢
      • 2017-12-11
      • 2013-12-05
      • 2018-11-17
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2012-04-27
      • 1970-01-01
      相关资源
      最近更新 更多