Scala 展平要映射的选项的贴图

Scala 展平要映射的选项的贴图,scala,Scala,我有一个Map[a,Option[B]],进行展平以获得Map[a,B]的最佳方法是什么 我知道对于一个列表,我们可以使用flatte,但是这个结构是不同的,它们是不同的,所以你需要一种方法来定义如果一个值为None时会发生什么。我假设您希望忽略这些键,如果是,您可以使用部分函数收集: map.collect { case (k, Some(v)) => k -> v } 或者用一个字母来表示理解 for ((k, Some(v)) <- map) yield k -

我有一个
Map[a,Option[B]]
,进行展平以获得
Map[a,B]
的最佳方法是什么


我知道对于一个列表,我们可以使用flatte,但是这个结构是不同的,它们是不同的,所以你需要一种方法来定义如果一个值为None时会发生什么。我假设您希望忽略这些键,如果是,您可以使用部分函数收集:

map.collect {
  case (k, Some(v)) => k -> v
}
或者用一个字母来表示理解

  for ((k, Some(v)) <- map) yield k -> v
((k,一些(v))v的
如果您不介意双重迭代:

map.filter(_._2.nonEmpty).mapValues(_.get)
例如:

scala> Map(1 -> Some(1), 2 -> None).filter(_._2.nonEmpty).mapValues(_.get)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)
scala> Map(1 -> Some(1), 2 -> None).flatten.toMap
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)

scala> def flat[K,V](kv: (K, Option[V])) = kv._2.map(kv._1 -> _).toList 
warning: there was one feature warning; re-run with -feature for details
flat: [K, V](kv: (K, Option[V]))List[(K, V)]

scala> Map(1 -> Option(1), 2 -> None).flatMap(flat)
res29: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)

或者使用这个隐含的:

implicit def flat[K,V](kv: (K, Option[V])) = kv._2.map(kv._1 -> _).toList
map flatMap flat
然后:

或不使用(潜在不安全)隐式:

implicit def flat[K,V](kv: (K, Option[V])) = kv._2.map(kv._1 -> _).toList
map flatMap flat
例如:

scala> Map(1 -> Some(1), 2 -> None).filter(_._2.nonEmpty).mapValues(_.get)
res9: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)
scala> Map(1 -> Some(1), 2 -> None).flatten.toMap
res2: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)

scala> def flat[K,V](kv: (K, Option[V])) = kv._2.map(kv._1 -> _).toList 
warning: there was one feature warning; re-run with -feature for details
flat: [K, V](kv: (K, Option[V]))List[(K, V)]

scala> Map(1 -> Option(1), 2 -> None).flatMap(flat)
res29: scala.collection.immutable.Map[Int,Int] = Map(1 -> 1)

是的,我没有明确指出我不想要没有值的键,非常感谢你的回答!实际上((k,一些(v))的
v
是非常正确的!我会更新!该模式在上面而不是下面匹配吗,白痴…值得注意的是,
mapValues
返回地图上的视图,这可能不是OP想要的。@jhn取决于,如果mapValues中的代码像我的回答中那样是引用透明的,为什么有人会关心呢?对于Java序列化(如果出于某种原因仍在使用它),那么总是有.view.force或.map(identity)为什么要关心性能。@jhn首先,“如果您不介意双重迭代”的意思是“如果您不太关心性能”。其次,view实际上提高了大型集合的性能,因为它不会创建中间集合(因此较少GC),这就是为什么
mapValues
实际上创建了一个视图。当然,每次使用视图时都会调用
get
,但是性能损失是值得怀疑的(它仍然是线性的,其他任何东西都取决于具体情况)。除此之外,问题中没有具体的性能要求-“最优”并不意味着什么“性能高效”。@jhn,正如它所说,如果你真的因为每次
get
而发现严重的性能泄漏,那么你总是可以
view.force
,在大多数情况下我对此表示怀疑(因为它不会改变渐进复杂性)。这不是“最优的”“为了追求1%的性能改进,牺牲了代码的可读性。无论如何,只有性能测试(针对真实OP的情况)才能确定是否应该使用视图