Scala - Как обработать ключ, не найденный на карте, когда нужно пропустить несуществующие ключи без значений по умолчанию? - PullRequest
0 голосов
/ 24 февраля 2019

У меня есть набор строк и его использование в качестве ключевых значений для получения 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.Однако все еще не уверен, что это лучший подход.

1 Ответ

0 голосов
/ 24 февраля 2019

То, что значения JSON - это красная сельдь - это отсутствующий ключ, который выдает исключение.Есть метод с именем get, который извлекает значение из карты, обернутой в Option.Если мы используем Int s в качестве значений, которые у нас есть:

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 s.Теперь, если мы вернемся к вашему фактическому примеру, у нас будет другой слой, и этот 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 для создания примера:

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))
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...