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

Scala 折叠选项列表以查找第一个或最后一个选项,scala,folding,Scala,Folding,我试图折叠一个选项列表,以便返回第一个(或最后一个)Some值,如果没有任何Some值,则返回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 =>

我试图折叠一个选项列表,以便返回第一个(或最后一个)Some值,如果没有任何Some值,则返回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})
                                 ^
scala>val opts=List(无、部分(1)、无、部分(2)、无)
选项:List[选项[Int]]=List(无,一些(1),无,一些(2),无)
scala>选择foldLeft(None)((a,io)=>a匹配{case None=>io;case Some(i)=>
a} )
:9:错误:对象无不接受参数
选择foldLeft(None)((a,io)=>a匹配{case None=>io;case Some
(i) =>a})
^

不知道我做错了什么。另外,可能有一种更简单的方法,使用高阶函数,但我没有注意到。

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

opts.flatten.headOption
opts.flatten.lastOption
最后一个要素是:

opts.flatten.headOption
opts.flatten.lastOption
展平
方法将取消列表中所有
选项
值的装箱,并删除所有
headOption
/
lastOption
将为列表中的第一个/最后一个元素返回
Some
,如果列表为空,则返回
None

非常简单,但对于长列表,它将尝试平展所有内容,因为它并不懒惰。(我认为
view
在这方面也帮不了我们,但我不太确定。)

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

opts.dropWhile(_.isEmpty).headOption.flatMap(identity)
不幸的是,我们不能在这里使用
flatten
,因为这将返回一个通用的
Iterable[Int]
和no
选项
,因此我们必须选择较长的惯用语
flatMap(identity)

编辑:注意:


会更好。

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

1) 您缺少下面的
选项
。只能使用中缀符号将
a.m(b)
转换为
a.m b
。foldLeft方法的形式为
a.m(b)(c)
。所以要么这样写,要么包含括号
(amb)(c)

2) 您需要将
None
参数化为
选项[Int]
:这里将其解释为
None
对象,而不是
选项[Int]
实例的值

因此,这将起作用:

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

为什么要这么麻烦

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

启动
Scala 2.9
,可以使用提取第一个定义的选项:

List(None, Some(1), None, Some(2), None).collectFirst { case Some(x) => x }
// Option[Int] = Some(1)
这将在第一个定义的
选项
处停止迭代,并避免在查找其头部之前展平整个
列表


启动您可以使用的
Scala 2.13
,这与
find
相反(在等待可能的
collectLast
?)


似乎find会返回它找到的第一个。有办法找到列表中的第n个或最后一个吗?我认为对于最后一个,您必须在之前反转列表。
opts.dropWhile(u.isEmpty)。headOption
返回
Option[Option[Int]]
,对吗?!但是为什么双精度选项上的
展平
不返回
选项[Int]
?根据
ev:@PeterSchmitz:ScalaDoc所指的夜间构建,您是正确的。对于2.10,这确实是固定的(当然,除非他们出于某种原因恢复了更改)。另一方面,在Scala 2.9中,在
选项
上没有方法
展平
——只有隐式转换到
Iterable
,在这种情况下执行。@Debilski啊,太好了。我在看夜间文档时感到困惑,因为我的代码(2.9.1)的反应超出了预期。当然,我们应该带上合适的文件;)因为我还在学scala。。。还有没有找到第n个值的方法?@Trevor-
opts.view.filter(u.nonEmpty).drop(n-1).headOption.flatte
是一种查找
n
第项的方法,而不必整平整个列表。应该指出的是,
flatte
将返回
列表,而不是像其他答案一样返回
选项。@LuigiPlinge您在“n”值的情况下是什么意思?是的,那个例子不起作用。它将抛出一个异常,并返回
List
。我把它拿走了。但是答案中的代码按预期返回
选项
。嗯,对我来说不是这样,在2.9.0中:它返回
Iterable[Int]=List(2)
。从Debilski在问题中的回答来看,这可能是2.9和2.10之间的差异。