在Scala中合并两个LinkedHashMap

时间:2017-12-05 08:59:22

标签: scala dictionary merge linkedhashmap

拥有此代码

def mergeWith[K, X, Y, Z](xs: mutable.LinkedHashMap[K, X], ys: mutable.LinkedHashMap[K, Y])(f: (X, Y) => Z): mutable.LinkedHashMap[K, Z] =
  xs.flatMap {
    case (k, x) => ys.get(k).map(k -> f(x, _))
  }

它给了我这个:

val map1 = LinkedHashMap(4 -> (4), 7 -> (4,7))
val map2 = LinkedHashMap(3 -> (3), 6 -> (3,6), 7 -> (3,7))

val merged = mergeWith(map1,map2){ (x, y) => (x, y) }
merged: scala.collection.mutable.LinkedHashMap[Int,(Any, Any)] = Map(7 -> ((4,7),(3,7)))

但我想要的是:

merged: scala.collection.mutable.LinkedHashMap[Int,(Any, Any)] = Map(3 -> (3), 4 -> (4), 6 -> (3,6), 7 -> ((4,7),(3,7)))

如何修改我的代码以获取它?

1 个答案:

答案 0 :(得分:1)

不能使用当前的mergeWith()签名。特别是,您尝试创建LinkedHashMap[K,Z]但没有Z输入。获得Z的唯一方法是调用f(),这需要XY作为传递的参数。

因此,如果xs的类型为LinkedHashMap[Int,Char]且元素为(2 -> 'w'),而ys的类型为LinkedHashMap[Int,Long]且元素为(8 -> 4L),那么您将调用f(c:Char, l:Long),以便为[K,Z]2两个键设置8条目?不可能。

如果可以简化mergeWith()签名,您可以执行类似的操作。

def mergeWith[K,V](xs: collection.mutable.LinkedHashMap[K, V]
                  ,ys: collection.mutable.LinkedHashMap[K, V]
                  )(f: (V, V) => V): collection.mutable.LinkedHashMap[K,V] = {
  val ns = collection.mutable.LinkedHashMap[K,V]()
  (xs.keySet ++ ys.keySet).foreach{ k =>
    if (!xs.isDefinedAt(k)) ns.update(k, ys(k))
    else if (!ys.isDefinedAt(k)) ns.update(k, xs(k))
    else ns.update(k, f(xs(k), ys(k)))
  }
  ns
}

这会为您所给出的示例产生所需的结果,但它具有许多不良品质,其中最重要的是可变数据结构。

顺便说一句,没有Tuple1这样的事情,所以(4)4是一回事。每当您看到Any类型时,这都是一个很好的迹象,表明您的设计需要重新思考。