2016-05-08 121 views
2

比方說,我有一個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

選項映射方法,所以你可以(我認爲應該)以同樣的方式做轉換你已經爲Seq完成了。 –

回答

8

雙層嵌套需要雙映射,所以是的,在香草scala中,你所做的是正確的。

然而,如果我們考慮到理論了一秒鐘,兩ListFuturemap操作,這使得他們Functors(這是一個過於簡單化,但包涵)

兩個Functors一般可以組成,因此您可以編寫的FutureFunctorList以實施「聯合」操作。

下面是一個使用cats一個例子:

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")) 

當然,你可以做同樣的Option

val futureOptionF = Functor[Future].compose(Functor[Option]) 
val data = Future.successful(Option(42)) 
futureOptionF.map(data)(_.toString) // Future(Some("42")) 

獎勵,你可以使用同樣的技術,無論嵌套的深度:

type ListOption[+A] = List[Option[A]] 
implicit val listOptionF = Functor[List].compose(Functor[Option]) 
val futureListOptionF = Functor[Future].compose(Functor[ListOption]) 

// the above three lines could just be 
// val futureListOptionF = Functor[Future].compose(Functor[List].compose(Functor[Option])) 
// if only SI-2712 were fixed 

val data = Future.successful(List(Some(42), None, Some(2))) 

// triple nesting? Still a single map! 
futureListOptionF.map(data)(_.toString) // Future(List(Some("42"), None, Some("2"))) 
+0

一個小問題:OP有一個Future [Seq [Int]]而不是Future [List [Int]],所以他被強制執行雙映射將Seq轉換爲列表 – lambdista

+0

'Seq'是一個抽象特徵,其缺省值實現是'List',所以OP的'Seq'可能已經是'List'了。否則,需要關於具體用例的更多細節 –

+0

但我認爲它看起來類型不是具體值,所以如果你有val數據:Future [Seq [Int]] = Future.successful(List(1,2, 3))你需要手動將其轉換爲List來使其工作 – lambdista

5

個人而言,我沒有看到任何嵌套地圖的錯誤。你只需要格式化和縮進更好它:

future.map { seq => 
    seq.map(_.toString) 
    } 

有些人還覺得在這種情況下for理解有用的(和更是這樣,當你需要處理的幾個期貨在一起)。

for { 
    seq <- future 
} yield seq.map(_.toString)