Scala 地图合并功能的改进

Scala 地图合并功能的改进,scala,Scala,我正在写一个函数来合并两个地图。这就是我到目前为止所做的: def merge[K, V1, V2, V3](left: Map[K, V1], right: Map[K, V2]) (fn: (Option[V1], Option[V2]) => V3): Map[K, V3] = { val r = (left.keySet ++ right.keySet) map { key => (key -> fn(left.get(key), rig

我正在写一个函数来合并两个地图。这就是我到目前为止所做的:

def merge[K, V1, V2, V3](left: Map[K, V1], right: Map[K, V2])
    (fn: (Option[V1], Option[V2]) => V3): Map[K, V3] = {
  val r = (left.keySet ++ right.keySet) map {
    key =>
      (key -> fn(left.get(key), right.get(key)))
  }
  r.toMap
}
该函数本身起作用。您可以按如下方式使用该函数:

val m1 = Map(1 -> "one", 3 -> "three", 5 -> "five")
val m2 = Map(1 -> "I", 5 -> "V", 10 -> "X")
merge(m1, m2) { (_, _) } 
// returns: 
// Map(1 -> (Some(one),Some(I)), 
//     3 -> (Some(three),None), 
//     5 -> (Some(five),Some(V)), 
//     10 -> (None,Some(X)))
我有两个问题:

  • 我担心
    .get
    .toMap
    调用的性能和计算复杂性。有人能改进实施吗
  • 我希望使用默认函数生成一对值(
    {({,{)}
    )。我不能很好地理解语法
  • 编辑:
    虽然我最初说的是性能,但我指的是计算复杂性。我猜这个函数在O(n•ln(n))时间内执行。看起来我的函数在O(n)中大致执行。可以在O(ln(n))中完成吗?

    对于默认函数文本使用:

    (fn: (Option[V1], Option[V2]) => V3 = 
      (x: Option[V1], y: Option[V2]) => Tuple2(x,y))
    
    您必须像这样使用merge:
    merge(m1,m2)(

    我想说的是,在对实际数据进行一些测量之前,不要担心性能

    编辑:关于性能,通过提供一个视图而不是构建一个映射,您可以以查找为代价快速“构建”——假设我们处理的是不可变映射。因此,根据实际数据和用例,您可以为某些操作获得更好的性能,但这需要权衡

    class MergedView[K, V1, V2, V3](
        left: Map[K, V1], right: Map[K, V2]
      )(fn: (Option[V1], Option[V2]) => V3 = (x: Option[V1], y: Option[V2]) => Tuple2(x,y)
      ) extends collection.DefaultMap[K, V3] {
      def get(key: K): Option[V3] = (left.get(key), right.get(key)) match {
        case (None, None) => None
        case t => Some(fn(t._1, t._2))
      }
      lazy val tuples = (left.keys ++ right.keys).map(key => key -> get(key).get)
      def iterator: Iterator[(K, V3)] = tuples.iterator
    } 
    
    val r1 = new MergedView(m1, m2)() // use parens here for second param list.
    

    您不应该担心
    get
    ——是的,它会创建一个包装器对象,但是做任何其他事情都会很尴尬,除非分析器显示这是一个问题,否则您不应该尝试

    至于
    toMap
    ,是的,这可能会让你慢下来。您可以尝试使用


    关于
    get
    toMap
    的复杂性,查找和添加是不可变
    HashMap
    的有效常量时间,这是默认的
    Map
    。参见。

    回答问题1:您可以看看Scalaz的地图幺半群类型类,如Eric Torreberre所述。你的问题有点不同,但它可能会给你一些想法。请看上面的例子。@Kipton地图幺半群令人印象深刻。我必须考虑一下这是否适用。我不太担心创建包装器对象(我无论如何都需要)的性能,而担心n次调用O(ln(n))函数的性能。@dave查找(即,
    get
    )对于默认映射(HashMap)来说是有效的常量时间(取决于哈希质量)。请参阅Scala系列的详细信息。优秀的链接!我一直在寻找类似的东西。从来没有想过要创建一个视图对象。非常有趣!这对我的用例没有帮助,但我会在将来记住这一点。huynhjl这太棒了@戴夫,我被你的回答搞糊涂了,因为这不是一个通用的解决方案。我可以用…将视图转换回地图。。。r1。toMap@huynhjl,我如何将我自己的密钥排序引入到这个中?谢谢。@Core-我已经忘了为什么它在我的特殊情况下不起作用。