在IndexedSeq中获得最小Int [(Int,Future [Long])]其中Long> 0

时间:2014-06-24 19:57:42

标签: scala future

我有一个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失败的情况。

4 个答案:

答案 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.sequencemap操作组合在一起。 foldLeft结合filterminBy中的所有逻辑,并生成相应的Option

Future.traverseFuture.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)
  }
}