2016-01-14 37 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)]]