首页 > 解决方案 > 展平具有 Option[T] 值的地图

问题描述

我有一张地图,目前以类似的顺序表示Seq[(String, Option[T])]。我不关心None地图中的值,因为我想做一些操作,比如对它们进行排序,这样我就可以确定要使用哪个键。我可以做这样的事情:

val mapping: Seq[(String, Option[Foo])]

mapping.filter(_._2.isDefined)
    .sortBy(_._2.get.someInt)
    .headOption.map(_._1)

...但必须有更好的方法来写这个。特别是,这get让我感到不舒服,因为该值仍然是 type Option[Foo],尽管其中不应该有任何None值。

有没有更好的办法?

标签: scala

解决方案


Foo我假设和有以下定义mapping

case class Foo(someInt: Int)
val mapping: Seq[(String, Option[Foo])] = Seq(("a", Some(Foo(42))), ("b", None))

你有几个选择:

collect

collect方法将模式匹配与过滤相结合:

mapping.collect{case (s,Some(Foo(i))) => (s,i) }.sortBy(_._2).headOption.map(_._1)

for-yield

for或者,您可以使用-达到相同的效果yield,它也会抛出所有不匹配的元素:

(for ((s, Some(Foo(n))) <- mapping) yield(s, n)).sortBy(_._2).headOption.map(_._1)

O(N) 解决方案minBy

还要注意,为了提取最大值/最小值对整个集合进行排序是不必要的:有maxBy/minBy为此:

Option(for ((s, Some(Foo(n))) <- mapping) yield (s, n))
  .filter(_.nonEmpty)
  .map(_.minBy(_._2)._1)

将整个序列包装成Option是必要的,这样我们就可以过滤掉序列为空的情况,因此我们不会minBy在空序列上调用。


推荐阅读