我有一组Strings,并将其用作从Map获取JValues的键值:
val keys: Set[String] = Set("Metric_1", "Metric_2", "Metric_3", "Metric_4")
val logData: Map[String, JValue] = Map("Metric_1" -> JInt(0), "Metric_2" -> JInt(1), "Metric_3" -> null)
在以下方法中,我正在解析每个指标的值。首先获取所有值,然后进行过滤以除去空值,然后将现有值转换为布尔值。
val metricsMap: Map[String, Boolean] = keys
.map(k => k -> logData(k).extractOpt[Int]).toMap
.filter(_._2.isDefined)
.collect {
case (str, Some(0)) => str -> false
case (str, Some(1)) => str -> true
}
在keys
映射中找不到logData
之一时,我遇到了一个问题。所以我得到一个java.util.NoSuchElementException: key not found: Metric_4
。
在这里,我正在使用extractOpt
从JSON提取值,并且不需要默认值。因此,extractOrElse
可能无济于事,因为我只需要获取现有键的值并跳过不存在的键。
在logData
映射中不存在密钥的情况下,处理案件的正确方法是什么?
UPD :我已经通过.map(k => k -> apiData.getOrElse(k, null).extractOpt[Int]).toMap
达到了预期的结果。但是仍然不确定这是最好的方法。
答案 0 :(得分:5)
值是JSON是一个红色鲱鱼-这是引发异常的丢失键。有一种称为get
的方法,该方法从包装在Option中的映射中检索值。如果我们使用Int
作为值,则我们有:
val logData = Map("Metric_1" -> 1, "Metric_2" -> 0, "Metric_3" -> null)
keys.flatMap(k => logData.get(k).map(k -> _)).toMap
> Map(Metric_1 -> 1, Metric_2 -> 0, Metric_3 -> null)
使用flatMap
代替map
意味着解开Some
结果并丢弃None
。现在,如果返回到您的实际示例,我们还有另一层,并且flatMap将消除Metric_3 -> null
项:
keys.flatMap(k => logData.get(k).flatMap(_.extractOpt[Int]).map(k -> _)).toMap
您也可以使用for
理解来重写它:
(for {
k <- keys
jv <- logData.get(k)
v <- jv.extractOpt[Int]
} yield k -> v).toMap
我使用Success
和Failure
来代替JSON值,以避免为了建立示例而必须使用json4s设置shell:
val logData = Map("Metric_1" -> Success(1), "Metric_2" -> Success(0), "Metric_3" -> Failure(new RuntimeException()))
scala> for {
| k <- keys
| v <- logData.get(k)
| r <- v.toOption
| } yield k -> r
res2: scala.collection.immutable.Set[(String, Int)] = Set((Metric_1,1), (Metric_2,0))