scala map - 如果密钥不存在,尝试不同密钥的最佳方法是什么

scala map - what's the best way to try a different key if a key doesn't exist

给定一个 Scala 中的 Map,我想尝试第一个键,如果找不到,请尝试另一个键,如果再次找不到,return None。以下按预期工作:

val scores: Map[String, Int] = Map("Alice" -> 10, "Bob" -> 3)
val singleGet: Option[Int] = scores.get("NotAKey")
println(singleGet) // None
val doubleGet = scores.getOrElse("NotAKey", scores.get("NotAKeyAgain")) // works ok if no type
println(doubleGet) // None

但是如果我为 doubleGet 输入类型,它会出错:

val doubleGet: Option[Int] = scores.getOrElse("NotAKey", scores.get("NotAKeyAgain")) // ERROR

"Expression of type Any doesn't conform to expected type Option[Int]"

那么最好的方法是什么?

你对自己想做什么有很好的直觉,那就是:
"test one key, if that does not exists, then check the second one".

此外,您对 return 类型的看法是正确的,因为您没有提供任何默认值,并且不能保证任何一个键都存在。
但是,您的问题是 scores.getOrElse("NotAKey", scores.get("NotAKeyAgain")) 将 return Any.
为什么?因为 getOrElse return 是两个备选方案的 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)