我有两个案例类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]]]
。
来自id
的每个ids
应该是地图中的一个关键字,当id -> Some(q)
被成功检索时(即出现在retrieve
的结果中),也会id -> None
转化成功。否则,地图应包含Empty
或{{1}}。
我怎样才能做到这一点?
答案 0 :(得分:3)
.id
或P
上有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
地图的构建工作在线性时间