Scala конвертировать карту [A, Seq [Future [Option [B]]]] в будущее [Map [A, Seq [B]]]? - PullRequest
0 голосов
/ 04 апреля 2020

Я застрял и мне было интересно, как я могу конвертировать Map[A, Seq[Future[Option[B]]]] в Future[Map[A, Seq[B]]]?

Ответы [ 2 ]

1 голос
/ 04 апреля 2020

Простейшим способом будет что-то вроде:

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

данных в вашей текущей форме, однако вынуждает нас делать это сложным образом.

0 голосов
/ 04 апреля 2020

Эта версия позволяет избежать повторной группировки данных путем преобразования Map в List и затем обратно.

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)

Внутренний map использует Future.sequence для преобразования каждой записи из * От 1008 * до Future[A -> Seq[B]].

Внешний Future.sequence преобразует List[Future[A -> Seq[B]]] в Future[List[A -> Seq[B]]].

Внешний map преобразует этот List обратно в Map .

Компилируется, чтобы типы были правильными, но я не проверял их на реальных данных

...