使用for comprehension scala过滤两个Future [Seq]

时间:2017-04-19 14:42:16

标签: scala for-comprehension flatmap

我有一些函数会返回未来的元组元素(Int,Int)列表。为简单起见,我将定义两个期货

  val f1 = Future {
    List((8, 3), (2, 1), (4, 2), (3, 4))
  }
  val f2 = Future {
    List((2, 3), (5, 1), (7, 9))
  }

我想过滤并使用以下标准从这两个未来列表中获取元素。

  

在第二个位置包含相同元素的元组

在此方案中,输出应为

List(((2,1),(5,1)), ((8,3),(2,3))) 

我可以使用普通列表(没有期货)进行此操作,如下所示:

val l1 = List((4, 2), (3, 4), (2, 1), (8, 3))
val l2 = List((2, 3), (5, 1), (7, 9))

val o = for {
  a <- l1
  b <- l2 if a._2 == b._2
} yield (a, b)

如何用期货来做?

3 个答案:

答案 0 :(得分:3)

如果您想使用完整的理解,可以使用其他解决方案:

val o2 = for {
  l1 <- f1
  l2 <- f2
} yield for {
  a <- l1
  b <- l2 if a._2 == b._2
} yield (a,b)

当然,你将拥有Future,所以你需要等待结果或将其进一步传递给将要处理它的东西

答案 1 :(得分:1)

另一种可能性是来自scalaz的ListT monad变换器(although it violates the associative law):

import scala.concurrent.ExecutionContext.Implicits.global
import scala.concurrent.{Await, Future}
import scalaz.Scalaz._
import scalaz._
import scala.concurrent.duration._

def main(args: Array[String]): Unit = {
  val f1 = Future {
    List((8, 3), (2, 1), (4, 2), (3, 4))
  }

  val f2 = Future {
    List((2, 3), (5, 1), (7, 9))
  }

  val first = ListT[Future, (Int, Int)](f1)
  val second = ListT[Future, (Int, Int)](f2)

  val res = for {
    a <- first
    b <- second if a._2 == b._2
  } yield (a, b)

  println(Await.result(res.run, 3 seconds))
}

答案 2 :(得分:1)

Scala 2.12向zipWith添加了Future

f1.zipWith(f2) {
  (l1, l2) => for {
    a <- l1
    b <- l2 if a._2 == b._2
  } yield (a, b)
}

有关详细信息,请参阅此博文:http://viktorklang.com/blog/Futures-in-Scala-2.12-part-2.html