过滤映射中的空值

35

我在网上搜索了一下,但是还没有找到一个好的答案来过滤掉 map 中值为 None 的任何条目。比如我有一个这样的 map:

val map = Map[String, Option[Int]]("one" -> Some(1), 
                                   "two" -> Some(2), 
                                   "three" -> None)

我希望最终返回一个仅包含("one", Some(1))("two", Some(2))这对键值的映射表。我知道当你有一个列表时,可以使用flatten来实现,但我不确定如何在不将映射表拆分为键和值的情况下实现该效果,然后尝试重新合并它们。

3个回答

58

如果你正在过滤掉None值,你可以同时提取Some值,最终得到一个Map[String,Int]

scala> map.collect { case (key, Some(value)) => (key, value) }
res0: scala.collection.immutable.Map[String,Int] = Map(one -> 1, two -> 2)

42

就像scala.collection中的每种集合类型一样,Map定义了filter方法,而Option则定义了isDefined方法,对于Some返回true,对于None返回false。你可以通过结合这两个方法来过滤掉None值:

scala> map.filter(_._2.isDefined)
res4: scala.collection.immutable.Map[String,Option[Int]] = Map(one -> Some(1), two -> Some(2))

不错。我本来猜不到语法。但是对于“_.”还有点困惑。据我所知,我们是在告诉它去第一个(当前)对的第二个项目(值)吗? - KChaloux
2
在这种情况下,_ 是指传递给 filter 方法的函数文字的第一个参数。它是 x => x._2.isDefined 的简写。 - Nikita Volkov
"_2" 来自于 Tuple - fracz

7

同时,您还可以使用以下两种方法之一来过滤Map中的非空值:

map.filterKeys(map(_)!=None)

或者

for((k,v) <- map if(v!=None)) yield(k,v)

这种方法提供了一个通用的filterValues方法,而这种方法在Map中并不存在。
我很想有这样的方法,因为其他替代方案都不是完美的。

[稍后更新] 这是一个更好的版本,它不会在每个条目上进行查找,并且仍然可以清晰地读取。

map.filter({case(x,y)=> y!=None})


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接