У вас есть хорошая интуиция в том, что вы хотите сделать, а именно:
"проверить один ключ, если его не существует, то проверить второй" .
Кроме того, вы правильно указали тип возвращаемого значения, потому что вы не указали никаких значений по умолчанию, и нет гарантии, что любой из этих ключей должен существовать.
Но ваша проблема в том, что scores.getOrElse("NotAKey", scores.get("NotAKeyAgain"))
вернет Любой .
Почему?Потому что getOrElse
возвращает LUB (наименьшая верхняя граница) обеих альтернатив.В этом случае значение по умолчанию - Option[Int]
, но тип успешного извлечения первого ключа - Int
.
. Что вам действительно нужно, так это способ составить две опции ,где второй используется в случае, если первый не существует.И это именно то, что orElse
делает.
Вы можете создать несколько методов расширения поверх Map , чтобы упростить использование.
implicit class MapOps[K, V](private val map: Map[K, V]) extends AnyVal {
def doubleGet(key1: K, key2: K): Option[V] =
map.get(key1) orElse map.get(key2)
def doubleGetOrElse[V1 >: V](key1: K, key2: K)(default: => V1): V1 =
(map.get(key1) orElse map.get(key2)).getOrElse(default)
def multiGet(keys: K*): Option[V] =
keys.iterator.map(key => map.get(key)).foldLeft(Option.empty[V])(_ orElse _)
def multiGetOrElse[V1 >: V](keys: K*)(default: => V1): V1 =
keys.iterator.map(key => map.get(key)).foldLeft(Option.empty[V])(_ orElse _).getOrElse(default)
}
val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3)
scores.doubleGet("A", "B") // res: Option[Int] = None
scores.multiGet("A", "Alice", "B") // res: Option[Int] = Some(10)