在 Scala 中将 Futures 列表合并到 Map 中
Consolidate a list of Futures into a Map in Scala
我有两个案例 类 P(id: String, ...)
和 Q(id: String, ...)
,以及两个返回期货的函数:
一个在给定 id-s 列表的情况下检索对象列表的方法:
def retrieve(ids: Seq[String]): Future[Seq[P]] = Future { ... }
如果没有找到所有 id-s,结果的长度可能比输入的短。
进一步将 P
转换为其他类型的 Q
:
def transform(p: P): Future[Q] = Future { ... }
我最后想要的是,如下。给定ids: Seq[String]
,计算一个Future[Map[String, Option[Q]]]
.
ids
中的每个 id
都应该是映射中的键,成功检索时带有 id -> Some(q)
(即出现在 retrieve
的结果中)并且也转型成功。否则,地图应包含 id -> None
或 Empty
.
我怎样才能做到这一点?
P
或 Q
上有 .id
属性 吗?您将需要一个来创建地图。是这样的吗?
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]
。
编辑:现在假定 P
有一个等于原始 id
-String 的成员 id
,否则 id
之间的连接p
s 在 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
}
}
从检索到的 P
和转换后的 Q
构建一个中间 Map
,因此 ids
-to-q-Options
映射的构建可以在线性时间。
我有两个案例 类 P(id: String, ...)
和 Q(id: String, ...)
,以及两个返回期货的函数:
一个在给定 id-s 列表的情况下检索对象列表的方法:
def retrieve(ids: Seq[String]): Future[Seq[P]] = Future { ... }
如果没有找到所有 id-s,结果的长度可能比输入的短。
进一步将
P
转换为其他类型的Q
:def transform(p: P): Future[Q] = Future { ... }
我最后想要的是,如下。给定ids: Seq[String]
,计算一个Future[Map[String, Option[Q]]]
.
ids
中的每个 id
都应该是映射中的键,成功检索时带有 id -> Some(q)
(即出现在 retrieve
的结果中)并且也转型成功。否则,地图应包含 id -> None
或 Empty
.
我怎样才能做到这一点?
P
或 Q
上有 .id
属性 吗?您将需要一个来创建地图。是这样的吗?
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]
。
编辑:现在假定 P
有一个等于原始 id
-String 的成员 id
,否则 id
之间的连接p
s 在 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
}
}
从检索到的 P
和转换后的 Q
构建一个中间 Map
,因此 ids
-to-q-Options
映射的构建可以在线性时间。