我有一个很长的通话查询,我想通过它来映射和过滤结果并将调用结果传递给收集主体,这样我就可以使用它而无需再次调用它。
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
}
有优雅的解决方案吗?
答案 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
}