scala传递部分值来收集身体

时间:2016-03-01 16:22:43

标签: scala

我有一个很长的通话查询,我想通过它来映射和过滤结果并将调用结果传递给收集主体,这样我就可以使用它而无需再次调用它。

def veryLongFoo(i:Int):Option[Int] 

val myList = (1 to 100).toList
myList.collect{ case x if veryLongFoo(x).isDefined =>    
  val y = veryLongFoo(x).get // I want to avoid calling veryLongFoo(x) again
  y
}

有优雅的解决方案吗?

4 个答案:

答案 0 :(得分:4)

简单地:

(1 to 100).flatMap(veryLongFoo)
为每个veryLongFoo计算

Int并返回Option[Int]。然后将此Option[Int]转换为Traversable(通过隐式CanBuildFrom),如果它是None,则包含0个元素,如果它是Some,则只转换为1个元素}。然后,由于Traversable操作,所有获得的flatMap被连接在一起。

答案 1 :(得分:2)

稍有不实的回答,请使用extractor

def veryLongFoo(i:Int): Option[Int] = ???

object Wrap {
  def unapply(x: Int): Option[Int] = veryLongFoo(x)
}

val myList = (1 to 100).toList
myList.collect {
  case Wrap(x) => x // presumably do something else with x...
}

但实际上并没有这样做,请改用flatMap

答案 2 :(得分:0)

您可能希望不返回选项而是返回未来

import scala.concurrent._
import scala.concurrent.duration._

def veryLongFoo(i:Int):Future[Int]

val myList = (1 to 100).toList
myList.collect{ case x =>
    Await.result(veryLongFoo(x), 1 minute) // I want to avoid calling veryLongFoo(x) again
}

并且在veryLongFoo内你需要维护一些Map[Int, Future[Int],因此如果未来不存在 - 你需要启动它并放入地图。一旦未来完成 - 它将简单地返回结果。如果它还在等待计算 - 那么Await将等到它完成。

答案 3 :(得分:0)

我先将它映射,然后收集:

def veryLongFoo(i:Int):Option[Int]

val myList = (1 to 100).toList

myList.map(veryLongFoo)
    .collect {
      case Some(result) => result
    }