sam*_*mba 0 collections json scala
我有一组字符串并使用它作为键值来从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)
Run Code Online (Sandbox Code Playgroud)
在下面的方法中,我正在解析每个度量的值.首先获取所有值,然后过滤以除去空值,然后将现有值转换为布尔值.
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
}
Run Code Online (Sandbox Code Playgroud)
keys当地logData图中找不到其中一个时,我遇到了问题.所以我正在考虑java.util.NoSuchElementException: key not found: Metric_4.
这里我extractOpt用来从JSON中提取一个值,不需要默认值.所以可能extractOrElse没有用,因为我只需要获取现有键的值并跳过不存在的键.
当logDataMap中没有键时,处理案例的正确方法是什么?
UPD:我已经达到了预期的效果.map(k => k -> apiData.getOrElse(k, null).extractOpt[Int]).toMap.但是仍然不确定这是最好的方法.
值为JSON的是一个红色鲱鱼 - 它是抛出异常的缺失键.有一种方法get可以从包含在Option中的映射中检索一个值.如果我们使用Ints作为我们的值:
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)
Run Code Online (Sandbox Code Playgroud)
使用flatMap而不是map手段解开Some结果并删除Nones.现在,如果我们回到你的实际例子,我们有另一个层,flatMap将消除该项Metric_3 -> null:
keys.flatMap(k => logData.get(k).flatMap(_.extractOpt[Int]).map(k -> _)).toMap
Run Code Online (Sandbox Code Playgroud)
您还可以使用for理解来重写它:
(for {
k <- keys
jv <- logData.get(k)
v <- jv.extractOpt[Int]
} yield k -> v).toMap
Run Code Online (Sandbox Code Playgroud)
我使用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))
Run Code Online (Sandbox Code Playgroud)