仅使用某些键映射

时间:2012-02-15 12:01:35

标签: scala

对于Scala中的地图,如果ms - (k, 1, m)返回包含ms 的所有映射的地图,除了,用于具有给定键x,1和m的任何映射。

然后,什么语句将返回ms的所有映射的映射,其中给定的键x,1和m。即我正在寻找ms的子集,其中只有k,1和m是键。

这很有效,但很糟糕:

scala> val originalMap = Map("age" -> "20", "name" -> "jack", "hobby" -> "jumping")
ms: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(age -> 20, name -> jack, hobby -> jumping)

scala> val interestingKeys = List("name", "hobby")
interesting: List[java.lang.String] = List(name, hobby)

scala> val notInterestingMap = originalMap -- interestingKeys
notInterestingMap: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(age -> 20)

scala> val interestingMap = originalMap -- notInterestingMap.keySet
interestingMap: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> jack, hobby -> jumping)

3 个答案:

答案 0 :(得分:7)

filterKeys可以提供帮助:

scala> originalMap.filterKeys(interestingKeys.contains)
res0: scala.collection.immutable.Map[java.lang.String,java.lang.String] = Map(name -> jack, hobby -> jumping)

答案 1 :(得分:7)

由于filterKeys基于任意谓词进行过滤,因此必须考虑地图中的每个键。这可能是好的或不是,取决于地图的大小等,但它绝对不是您描述的操作所必需的。我会使用以下内容:

interestingKeys.flatMap(k => originalMap.get(k).map((k, _))).toMap

这将是O(n)O(n log m),具体取决于您的地图实施情况(n的大小为interestingKeysm是地图的大小),而不是O(m log n)O(mn)

如果您真的想要~运营商,可以使用pimp-my-library pattern

class RichMap[A, B](m: Map[A, B]) {
  def ~(ks: A*) = ks.flatMap(k => m.get(k).map((k, _))).toMap
}

implicit def enrichMap[A, B](m: Map[A, B]) = new RichMap(m)

现在originalMap ~ ("name", "hobby")会返回Map(name -> jack, hobby -> jumping),正如您所期望的那样。

答案 2 :(得分:2)

我认为原始代码并没有那么糟糕,它可以很容易地转换为在关键集上运行的单行代码:

val interestingMap = originalMap -- (originalMap.keySet -- interestingKeys)

我觉得这很可读。