【问题标题】:Scala - How to handle key not found in a Map when need to skip non-existing keys without defaults?Scala - 当需要跳过没有默认值的不存在的键时,如何处理在地图中找不到的键?
【发布时间】:2019-07-17 17:05:49
【问题描述】:

我有一组字符串并将其用作键值以从 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 所期望的结果。但是仍然不确定这是最好的方法。

【问题讨论】:

    标签: json scala collections


    【解决方案1】:

    值是 JSON 是一个红鲱鱼 - 它是引发异常的缺失键。有一个名为get 的方法,它从包裹在选项中的映射中检索值。如果我们使用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)
    

    使用flatMap 而不是map 意味着解开Some 结果并删除Nones。现在,如果我们回到您的实际示例,我们还有另一个图层,该 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))
    

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-11-08
      • 1970-01-01
      • 1970-01-01
      • 2014-04-25
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多