假设我有Future[Seq[Int]]
我要转换为Future[Seq[String]]
。目前我这样做:
val futureSeqString = futureSeqInt.map( x => x.map(_.toString()))
这可行,但嵌套地图似乎有点尴尬。 Future[Option[Int]]
的等效转换稍微好一点,但仍然不觉得我这样做是最好的方式:
val futureOptionString = futureOptionInt.map {
case Some(x) => x.toString();
case _ => None;
}
有没有更好的方法来解决这个问题?
答案 0 :(得分:8)
双重嵌套需要双重映射,所以是的,在vanilla scala中,你所做的是正确的。
但是,如果我们将该理论考虑一下,List
和Future
都会进行map
操作,这会使它们成为Functors
(这是过于简单化,但是忍受我)
两个Functors
可以通用,因此您可以撰写Functor
的{{1}}和Future
的{{1}}来实现“联合”{ {1}}操作。
以下是使用cats
的示例:
Functor
当然,您可以使用List
执行相同操作。
map
奖励,无论嵌套的深度如何,您都可以使用相同的技术:
import scala.concurrent.Future
import scala.concurrent.ExecutionContext.Implicits.global
import cats._
import cats.std.future._
import cats.std.list._
// create a `Functor[Future[List]`
val futureListF = Functor[Future].compose(Functor[List])
val data = Future.successful(List(1, 2, 3))
// only one map!
futureListF.map(data)(_.toString) // Future(List("1", "2", "3"))
答案 1 :(得分:5)
就个人而言,我没有看到嵌套地图有任何问题。你只需要更好地格式化和缩进它:
future.map { seq =>
seq.map(_.toString)
}
有些人还发现for
理解在这种情况下很有用(更重要的是,当你需要一起处理几个未来时)。
for {
seq <- future
} yield seq.map(_.toString)