Scala map - 如果密钥不存在,尝试使用其他密钥的最佳方法是什么



给定 Scala 中的 Map,我想尝试第一个键,如果没有找到,请尝试另一个键,如果再次找不到,则返回 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

"任何类型的表达式不符合预期的类型选项[Int]">

那么最好的方法是什么呢?

你对你想做的事情有一个很好的直觉,那就是:">
测试一个键,如果不存在,那么检查第二个键"。

此外,您在返回类型上是正确的,因为您没有提供任何默认值,并且不能保证任一键都应该存在。
但是,您的问题是scores.getOrElse("NotAKey", scores.get("NotAKeyAgain"))将返回Any
为什么?因为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)

相关内容

最新更新