在Scala中将Futures列表合并到Map中

时间:2018-02-18 21:53:05

标签: scala list dictionary optional future

我有两个案例类P(id: String, ...)Q(id: String, ...),以及两个返回期货的函数:

  1. 在给定id-s列表的情况下检索对象列表的人: def retrieve(ids: Seq[String]): Future[Seq[P]] = Future { ... }

    如果找不到所有id-s,结果的长度可能会短于输入。

  2. 进一步将P转换为其他类型Q的内容: def transform(p: P): Future[Q] = Future { ... }

  3. 我最终想要的是,以下内容。给定ids: Seq[String],计算Future[Map[String, Option[Q]]]

    来自id的每个ids应该是地图中的一个关键字,当id -> Some(q)被成功检索时(即出现在retrieve的结果中),也会id -> None转化成功。否则,地图应包含Empty或{{1}}。

    我怎样才能做到这一点?

2 个答案:

答案 0 :(得分:3)

.idP上有Q个属性吗?你需要一个来创建地图。像这样的东西?

for {
  ps <- retrieve(ids)
  qs <- Future.sequence(ps.map(p => transform(p))
} yield ids.map(id => id -> qs.find(_.id == id)).toMap

请注意,Map[String,Option[X]]通常不是必需的,因为如果您拥有Map[String,X]地图上的.get方法,则会为您提供Option[X]

答案 1 :(得分:2)

编辑:现在假设P的成员id等于原始id - 字符串,否则id和{{1}之间的连接在p之后丢失了。

retrieve

从已检索的def consolidatedMap(ids: Seq[String]): Future[Map[String, Option[Q]]] = { for { ps <- retrieve(ids) qOpts <- Future.traverse(ps){ p => transform(p).map(Option(_)).recover { // TODO: don't sweep `Throwable` under the // rug in your real code case t: Throwable => None } } } yield { val qMap = (ps.map(_.id) zip qOpts).toMap ids.map{ id => (id, qMap.getOrElse(id, None)) }.toMap } } 构建中间Map并转换P,以便Q - 到 - ids地图的构建工作在线性时间