我已经在我正在编写的库中出现过这种情况很多次了,而且我对目前为止提出的解决方案并不是特别满意。
假设我有一个昂贵的函数f,它接受类型为T的项并返回类型为Option [U]的值。现在,假设我有一个类型为T的集合,我希望检索f在跨T的元素执行时返回的第一个非None值,而不是为T的所有元素评估f(如果已找到该值)。
我想出的唯一方法是将F包装到Extractor对象中,并将其与scala的collectFirst方法一起使用。
例如:
object FMatch { def unapply(t : T) = f(t) }
collection.collectFirst{ case FMatch(result) => result }
这似乎有点不合适,我不确定f是否只对每个结果进行一次或两次评估(我还没有测试过这一点)。似乎有一个版本的collectFirst采用类型为T =>的参数是有用的。选项[U]而不是PartialFunction1 [T]。
有没有更优雅的方式来做到这一点我缺席了?
答案 0 :(得分:15)
在集合上使用一个视图,使其变为惰性并将该函数的调用推迟到最后一刻(例如,对于超出第一个匹配的元素,它将不会被调用):
xs.view map {f(_)} collectFirst {case Some(x) => x}
或
xs.view map {f(_)} find {_.isDefined}
或以无点的方式,根据Alexey的回应:
xs.view map {f} find {_.isDefined}
这应该会为您提供一些更方便地思考问题的替代方法:)
答案 1 :(得分:9)
使用此:
collection.toIterator.map(f).find(_.isDefined)
答案 2 :(得分:2)
@annotation.tailrec
def first[A, B](as: Traversable[A], f: A => Option[B]): Option[B] =
if (as.isEmpty) None
else f(as.head) match {
case s @ Some(_) => s
case _ => first(as.tail, f)
}