Scala: 从Map中移除空元素并压平

21

我有一张地图:

Map("key1" -> Some("value1"), "key2" -> None, "key3" -> Some("value3"))

我想要移除所有的 None 元素并且扁平化这个映射。最简单的方法是什么?我只找到这个方法:

Map("key1" -> Some("value1"), "key2" -> None, "key3" -> Some("value3")).filter(_._2.nonEmpty).map(item => (item._1 -> item._2.getOrElse(Nil)))

结果是:

Map(key1 -> value1, key3 -> value3)

你知道更好的方法吗?


1
为什么不使用filter + mapValues呢? - dk14
5个回答

43

我的观点是使用模式匹配:

Map("key1" -> Some("value1"), "key2" -> None, "key3" -> Some("value3")).collect {
  case (key, Some(value)) => key -> value
}
// Map(key1 -> value1, key3 -> value3)

Collect的功能类似于结合了map和filter


21
您可以使用 for 推导式 + 模式匹配:
for((k, Some(v)) <- yourMap) yield k -> v

2
现在这才是优雅的。我从来没有想过这个 :) - Felix
1
@felix 我非常赞同 - Lucian Enache

4
使用在地图上的分区,就像这样:
val (flattened,_) = map.partition(_._2.isDefined)

1

使用for循环的我的看法:

val m = Map("key1" -> Some("value1"), "key2" -> None, "key3" -> Some("value3"))
for( (key,value) <- m if(value.isDefined)) yield (key,value.get)

顺便提一下,同样的代码也可以写成 for((key, maybeVal) <- m; value <- maybeVal) yield key -> value - om-nom-nom
@om-nom-nom 或者甚至 for ((k, Some(v)) <- map ) yield k -> v - dk14
+1 是因为它还将地图类型从 Map[String, Option[String]] 更改为 Map[String, String],本质上不仅扁平化了值,还扁平化了类型。 - Haspemulator

0
你还可以定义以下辅助函数,它们允许使用更紧凑的语法。
implicit class RichPairedOptionIterableOps[A, B, Repr[_]](
    iterable: IterableOps[(A, Option[B]), Repr, Repr[(A, Option[B])]]
  ) {
    def collectWithSome: Repr[(A, B)] = iterable.collect { case (a, Some(b)) => a -> b }
    def collectWithNone: Repr[A] = iterable.collect { case (a, None) => a }
}

以你的例子为例:

Map("key1" -> Some("value1"), "key2" -> None, "key3" -> Some("value3")).collectWithSome

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