将额外信息绑定到将来的序列

时间:2014-05-10 17:00:50

标签: scala akka

假设我已经获得了一份期货清单,每个期货都链接到一个密钥,例如:

val seq: Seq[(Key, Future[Value])]

我的目标是在所有期货完成后生成一个关键值元组列表:

val complete: Seq[(Key, Value)]

我想知道是否可以使用序列调用来实现。例如,我知道我可以执行以下操作:

val complete = Future.sequence(seq.map(_._2).onComplete {
  case Success(s) => s
  case Failure(NonFatal(e)) => Seq()
}

但是这只会返回一系列Value对象,我会丢失Key和Value之间的配对信息。问题在于Future.sequence期待一系列期货。

我怎样才能增加这一点以保持完整序列中的键/值配对?

由于 DES

2 个答案:

答案 0 :(得分:4)

如何首先将Seq[(Key, Future[Value])]转换为Seq[Future[(Key, Value)]]

val seq: Seq[(Key, Future[Value])] = // however your implementation is

val futurePair: Seq[Future[(Key, Value)]] = for {
    (key, value) <- seq
} yield value.map(v => (key, v))

现在您可以使用序列来获取Future[Seq[(Key, Value)]]

val complete: Future[Seq[(String, Int)]] = Future.sequence(futurePair)

答案 1 :(得分:1)

使用unzipzip只是另一个答案的另一种表达方式。

scala> val vs = Seq(("one",Future(1)),("two",Future(2)))
vs: Seq[(String, scala.concurrent.Future[Int])] = List((one,scala.concurrent.impl.Promise$DefaultPromise@4e38d975), (two,scala.concurrent.impl.Promise$DefaultPromise@35f8a9d3))

scala> val (ks, fs) = vs.unzip
ks: Seq[String] = List(one, two)
fs: Seq[scala.concurrent.Future[Int]] = List(scala.concurrent.impl.Promise$DefaultPromise@4e38d975, scala.concurrent.impl.Promise$DefaultPromise@35f8a9d3)

scala> val done = (Future sequence fs) map (ks zip _)
done: scala.concurrent.Future[Seq[(String, Int)]] = scala.concurrent.impl.Promise$DefaultPromise@56913163

scala> done.value
res0: Option[scala.util.Try[Seq[(String, Int)]]] = Some(Success(List((one,1), (two,2))))

或者保存zippage:

scala> val done = (Future sequence fs) map ((ks, _).zipped)
done: scala.concurrent.Future[scala.runtime.Tuple2Zipped[String,Seq[String],Int,Seq[Int]]] = scala.concurrent.impl.Promise$DefaultPromise@766a52f5

scala> done.value.get.get.toList
res1: List[(String, Int)] = List((one,1), (two,2))