Scala collectFirst函数返回选项[U]

时间:2011-09-05 04:18:30

标签: scala optimization scala-collections

我已经在我正在编写的库中出现过这种情况很多次了,而且我对目前为止提出的解决方案并不是特别满意。

假设我有一个昂贵的函数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]。

有没有更优雅的方式来做到这一点我缺席了?

3 个答案:

答案 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)
  }