Простейшим способом будет что-то вроде:
val yourMap: Map[A, Seq[Future[Option[B]]]] = ...
val flattenedValues: Map[A, Future[Seq[B]]] = yourMap.mapValues { seqFuture =>
Future.sequence(seqFuture).map(seqOpt => seqOpt.flatten)
}
val seqOfFutures: Seq[Future[(A, Seq[B])]] = flattenedValues.toSeq.map {
case (a, futureSeqB) =>
future.map(optionB => a -> optionB)
}
val futureOfSeq: Future[Seq[(A, Seq[B])]] = Future.sequence(seqOfFutures)
val result: Future[Map[A, Seq[B]]] = futureOfSeq.map { seq =>
seq.groupBy(_._1).mapValues(_.map(_._2).flatten)
}
То, что у вас было до редакции вашего вопроса (Map[A, Future[Option[B]]
), было бы обработано проще с кошками, если бы вы определили 2 вещи
// as far as I can tell defined only in Alleycats
implicit def traverseMap[A]: cats.Traverse[Map[A, *]] = ...
// as far as I can tell defined in Cats
implicit def applicativeFuture: cats.Applicative[Future] = ...
тогда вы можете сделать это просто с помощью:
// assuming traverse syntax imported
val futureMap: Future[Map[A, Option[B]] = yourMap.sequence
данных в вашей текущей форме, однако вынуждает нас делать это сложным образом.