我有一个scala IndexedSeq[(Int, Future[Long])])
。
我想填写这个功能:
def getMininumIfCountIsPositive(distances: IndexedSeq[(Int, Future[Long])]): Future[Option[Int]] = {
}
如果不存在Long大于0的元素,则应返回Future of None。如果存在Long大于0的元素,则应返回最小关联Int的<。
这就是我现在所拥有的:
Future.sequence(distances.map {
case (index, count) => count.map(index -> _)
}) map {
s =>
Option(s.filter(_._2 > 0).minBy(_._1)._1)
}
但是,我不知道如何处理没有通过过滤器的元素或Futures失败的情况。
答案 0 :(得分:1)
将你的Int,Future [Long]序列映射到Future [(Int,Long)]序列:
val futureOfSequence = a map ( b: (Int, Future[Long]) => b._2 map ( c => (b._1,c)))
然后使用Future.sequence
将Future [(Int,Long)]的序列转换为Future [IndexedSeq(Int,Long)]
val sequenceOfFuture = Future.sequence(futureOfSequence)
现在你可以将Future展示给你的未来[Option [Int]]:
val finalResult = sequenceOfFuture map ( iSeq: IndexedSeq[(Int,Long)] => /* your logic goes here */ )
答案 1 :(得分:1)
相当啰嗦..
def get(a: IndexedSeq[(Int, Future[Long])]): Future[Option[Int]] = {
Future.sequence( // Convert the Seq[Future] to Future[Seq]
a.map{ case (index, f) =>
f.map(l => (index, l)) // map each Future to be paired with its index
.recover{ case _: Throwable => (0, 0L)} // recover failed Futures as (0, 0) since they'll be thrown out anyway
}
).map{ seq =>
Option(seq.minBy(_._2)) // Map the Seq to it's minimum element wrapped in Option
.filter(_._2 > 0) // Remove non-positives
.map(_._1) // Take the index
}
}
答案 2 :(得分:1)
这是一个高效的版本,源自问题中的一个:
Future.traverse(distances) {
case (index, count) => count.map(index -> _)
} map { _.foldLeft(None: Option[Int]) {
case (a, (_, x)) if x <= 0 => a
case (None, (i, _)) => Some(i)
case (Some(ai), (i, _)) => Some(ai min i)
}}
Future.traverse
允许我们将Future.sequence
和map
操作组合在一起。 foldLeft
结合filter
和minBy
中的所有逻辑,并生成相应的Option
。
Future.traverse
和Future.sequence
如果它们构建的任何期货都失败,则会产生失败的未来,因此您已经有适当的失败处理。
答案 3 :(得分:0)
trait Test2 {
import scala.concurrent.Future
import scala.concurrent.Future.{traverse, successful}
implicit def context: scala.concurrent.ExecutionContext
def logic(in: IndexedSeq[(Int, Long)]): Option[Int]
def getMininumIfCountIsPositive(a: IndexedSeq[(Int, Future[Long])]): Future[Option[Int]] = {
traverse(a) { case (i, f) => successful(i).zip(f) } map(logic)
}
}