折叠选项列表以查找第一个或最后一个

时间:2011-11-07 16:16:52

标签: scala folding

我正在尝试折叠选项列表,以便返回第一个(或最后一个)某些值,如果没有任何某些值则返回None。

scala> val opts = List(None, Some(1), None, Some(2), None)
opts: List[Option[Int]] = List(None, Some(1), None, Some(2), None)

scala> opts foldLeft(None)((a,io) => a match { case None => io; case Some(i) =>
a})
<console>:9: error: object None does not take parameters
              opts foldLeft(None)((a,io) => a match { case None => io; case Some
(i) => a})
                                 ^

不确定我做错了什么。也许有一种方法可以使用更高阶函数来简化这一操作,但here没有任何内容引起我的注意。

5 个答案:

答案 0 :(得分:14)

也许这可以解决您的问题 - 第一个要素:

opts.flatten.headOption

最后一个元素:

opts.flatten.lastOption

flatten方法将取消列出列表中的所有Option值并删除所有None值。对于列表中的第一个/最后一个元素,headOption / lastOption将返回Some,如果列表为空,则返回None

答案 1 :(得分:9)

tenshi’s answer非常简单,但对于长列表,它会尝试压扁所有内容,因为它不是懒惰的。 (我认为view也不会帮助我们,但我不太确定。)

在这种情况下,您可以使用:

opts.dropWhile(_.isEmpty).headOption.flatMap(identity)

很遗憾,我们无法在此处使用flatten,因为这会返回通用Iterable[Int]而不是Option,因此我们必须选择较长的成语flatMap(identity)

修改dave注意到:

opts.find(_.isDefined).flatMap(identity)

会更好。

答案 2 :(得分:4)

有更好的方法可以做到,但要回答提出的问题,你有两个问题

1)您错过了.之后的opts。您只能使用中缀表示法将a.m(b)转换为a m b。 foldLeft方法的格式为a.m(b)(c)。所以要么像那样写,要么包括括号(a m b)(c)

2)您需要将None参数化为Option[Int]:它在此被解释为None对象,而不是Option[Int]的值实例

所以这会奏效:

opts.foldLeft(None: Option[Int])(
  (a,io) => a match { case None => io; case Some(i) => a } )

答案 3 :(得分:2)

为什么会遇到这样的麻烦?

opts.find(_.nonEmpty).flatten
opts.reverse.find(_.nonEmpty).flatten

答案 4 :(得分:0)

Scala 2.9开始,您可以使用collectFirst提取第一个定义的选项:

List(None, Some(1), None, Some(2), None).collectFirst { case Some(x) => x }
// Option[Int] = Some(1)

这将在第一个定义的Option处停止迭代,并避免在寻找其头部之前弄平整个List


Scala 2.13开始,您可以使用findLast,它与find的相反(在等​​待可能的collectLast吗?)

List(None, Some(1), None, Some(2), None).findLast(_.isDefined).flatten
// Option[Int] = Some(2)