简体   繁体   中英

Scala convert Map[A, Seq[Future[Option[B]]]] to Future[Map[A, Seq[B]]]?

I've been stuck and was wondering how I can convert Map[A, Seq[Future[Option[B]]]] to Future[Map[A, Seq[B]]] ?

Simplest way would be something like:

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)
}

What you had before edition of your question ( Map[A, Future[Option[B]] ) would be handled simpler way with cats if you had 2 things defined

// 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] = ...

then you could do it simply with:

// assuming traverse syntax imported
val futureMap: Future[Map[A, Option[B]] = yourMap.sequence

the data in your current form, however, forces us to do it in a hard way.

This version avoid re-grouping the data by converting the Map to List and then back again.

val in: Map[A, Seq[Future[Option[B]]]] = ???

val out: Future[Map[A, Seq[B]]] =
  Future.sequence(
    in.toList.map {
      case (k, v) => Future.sequence(v).map(k -> _.flatten)
    }
  ).map(_.toMap)

The inner map uses Future.sequence to convert each entry from A -> Seq[Future[Option[B]]] to Future[A -> Seq[B]] .

The outer Future.sequence converts the List[Future[A -> Seq[B]]] to Future[List[A -> Seq[B]]] .

The outer map converts this List back to a Map .

This compiles so the types are right, but I have not tested it on any real data

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM