假设我已经获得了一份期货清单,每个期货都链接到一个密钥,例如:
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
答案 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)
使用unzip
和zip
只是另一个答案的另一种表达方式。
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))