如何在Scala中懒洋洋地映射和查找?

时间:2014-07-12 16:06:12

标签: scala collections

假设我有一个列表xs: List[X],其功能为f(x:X):Yg(y):Boolean。现在我需要找到第一个y = f(x)以便g(y) == true

def findY(xs: List[X], f: X => Y, g: Y => Boolean): Option[Y] = ???

我可以使用xs.map(f).find(g)执行此操作,但我不想遍历整个列表xs。我也不想使用流。您如何建议实施findY

3 个答案:

答案 0 :(得分:8)

使用视图

xs.view.map(f).find(g)

答案 1 :(得分:1)

而不是

xs.map(f).find(g)

只需转过来

xs.find(x => g(f(x)))

在这两种情况下都会返回Option[X]


如果你想要Option[Y],递归方法可以完成这项任务:

  @tailrec
  def findFirst[X, Y](xs: List[X], f: X => Y, g: Y => Boolean): Option[Y] = {
    xs match {
      case Nil =>
        None

      case h :: t =>
        val y = f(h)

        if (g(y)) {
          Some(y)
        } else {
          findFirst(t, f, g)
        }
    }
  }

答案 2 :(得分:0)

另一种可能性是使用collectFirst,它也会返回Option

xs.collectFirst{case x if g(f(x)) => f(x)}

唯一的缺点是如果找到匹配的东西,你会评估f(x)两次。 我不确定是否可以将结果f(x)绑定到某个变量。