Проверьте, все ли ключи присутствуют на карте - PullRequest
0 голосов
/ 03 мая 2020

Пусть есть карта config: Map[String, String].

И есть несколько ключей: "foo", "bar", ...

Мне нужно убедиться, что все ключи присутствуют в config. И если они присутствуют, мне нужно вызвать функцию со значениями для этих ключей на карте config:

fun(config("foo"), config("bar"), config(...), ...)

Решение является следующим:

val res = Option.when(config.contains("foo") & config.contains("bar") & config.contains(...) & ...)
    ( fun(config("foo"), config("bar"), config(...), ...) )

Или, может быть, :

val set = Set("foo", "bar", ...)
val res = Option.when(config.view.filterKeys(set).size == set.size)
    ( fun(config("foo"), config("bar"), config(...), ...) )

Оба подхода выглядят уродливо и неэффективно. Есть ли более краткий способ реализовать то же поведение?

Ответы [ 5 ]

2 голосов
/ 04 мая 2020

Так как набор ключей установлен на c, вам не нужно делать ничего слишком сложного.
Вам просто нужно попытаться получить каждую клавишу, и если все находятся в режиме вызова функции и обернуть результат в Некоторые , если нет, вернуть Нет .

for {
  value1 <- config.get("key1")
  // ...
  valueN <- config.get("keyN")
} yield fun(value1, ..., valueN)

Если у вас есть кошек , вы можете сделать это следующим образом.

(
  config.get("key1"),
  // ...
  config.get("keyN")
).mapN(fun(_).tupled)
1 голос
/ 03 мая 2020

Рассмотрим forall в сочетании с contains

val requiredKeys = List("foo", "bar")

if (requiredKeys forall config.contains) {
  // work with config
} else {
  // handler error
}

или на основе Том Крокетт Рассмотрим keySet подход

val requiredKeys = Set("foo", "bar")

if (requiredKeys subsetOf config.keySet) {
  // work with config
} else {
  // handler error
}
0 голосов
/ 05 мая 2020

Ниже приведен flatMap способ:

config.get("key1").flatMap(key1 =>
config.get("key2").flatMap(key2 =>
...
config.get("keyN").flatMap(keyN =>
fun(key1, key2, ..., keyN)
))...) 
0 голосов
/ 04 мая 2020

Это использование котов, очень распространенная библиотека FP:

import cats.implicits._

def fun(a: String, b: String, c: String): MyConfigClass = ???

val parsedOpt: Option[MyConfigClass] = 
  (config.get("a"), config.get("b"), config.get("c"))
  .mapN(fun)

Метод mapN делает то, что вы хотите, он извлечет все значения, если они существуют, и предоставит их для развлечения. Для любопытных, он полагается на тот факт, что Option является Applicative.

Чтобы показать его силу, вы также можете получить список недостающих ключей, чтобы узнать, где была проблема:

import cats.data._
def getConfig(key: String): Either[NonEmptyList[String], String] =
config.get(key).toRightNel(s"Key $key not found")

val parsedValidated: Either[NonEmptyList[String], MyConfigClass] =
  (getConfig("a"), getConfig("b"), getConfig("c"))
 .parMapN(fun)
0 голосов
/ 03 мая 2020

если у вас есть ключи as ("foo", "bar", ...). Map (config) возвращает значения, верно? тогда, если он содержит None, тогда не все ключи найдены. Я бы начал обдумывать эту идею.

Передача элементов списка в качестве параметров в функцию с переменными аргументами помогает здесь, поэтому val args = list.map (config); затем условие, чтобы проверить, все ли значения присутствуют, и, наконец, весело (аргументы: _ *).

как насчет этого?

...