2016-01-14 28 views
0

我有參數類型Future[List[MyRes]]的方法。 MyRes有兩個選項字段idname。現在我想創建地圖idname,如果兩者都存在。我能夠創建具有默認值的地圖,如下,但我不想有默認值,只是跳過空值的條目。根據Scala的未來列表的條件創建地圖

def myMethod(myRes: Future[List[MyRes]]): Future[Map[Long, String]] = { 
    myRes.map (
    _.map(
     o => 
     (o.id match { 
     case Some(id) => id.toLong 
     case _ => 0L 
     }) -> 
     (o.name match { 
     case Some(name) => name 
     case _ => "" 
     }) 
).toMap) 

有什麼建議嗎?

回答

3

您正在尋找collect :)

myRes.map { 
    _.iterator 
    .map { r => r.id -> r.name } 
    .collect { case(Some(id), Some(name) => id -> name } 
    .toMap 
} 

如果您MyRes啄是一個案例類,那麼就不需要第一.map

myRes.map { 
    _.collect { case MyRes(Some(id), Some(name)) => id -> name } 
    .toMap 
} 

collect就像.map,但它需要一個PartialFunction,並跳過它未定義的元素。這有點像你的match聲明,但沒有默認值。

更新: 如果我正確地讀你的評論,要記錄當任一領域是無,collect不會提供幫助的消息,但你可以做flatMap

myRes.map { 
    _.flatMap { 
    case MyRes(Some(id), Some(name)) => Some(id -> name) 
    case x => loger.warn(s"Missing fields in $x."); None 
    } 
    .toMap 
} 
+0

如何記錄無效的消息?第二種情況需要返回類型'map [Long,String]',但在我的情況下,它將只是'logger.warn(「...」)' –

+1

@αƞjiβ請參閱我的更新回答。這是你問的嗎? – Dima

+0

返回類型是'Future [List [AxiomResource]]'所以我們如何映射第一種情況。 –

0

嘗試這種情況:

def myMethod(myRes: Future[List[MyRes]]): Future[Map[Long, String]] = { 
    myRes.map (
    _.flatMap(o => 
     (for (id <- o.id; name <- o.name) yield (id.toLong -> name)).toList 
    ).toMap 
) 
} 

訣竅是通過使用flatMap並轉換OptionList壓扁List[Option[(Long,String)]]