在 Scala 中合并两个 LinkedHashMap
Merge two LinkedHashMap in Scala
有这个代码
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)))
如何修改我的代码获取?
当前的mergeWith()
签名无法完成。特别是,您正在尝试创建 LinkedHashMap[K,Z]
但没有 Z
输入。获得 Z
的唯一方法是调用 f()
,这需要 X
和 Y
作为传递参数。
因此,如果 xs
是类型 LinkedHashMap[Int,Char]
并且具有元素 (2 -> 'w')
,并且 ys
是类型 LinkedHashMap[Int,Long]
并且具有元素 (8 -> 4L)
,您将如何调用 f(c:Char, l:Long)
以便为键 2
和 8
提供一个 [K,Z]
条目?不可能。
如果可以简化 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
时,这都是一个很好的迹象,表明您的设计需要重新考虑。
有这个代码
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)))
如何修改我的代码获取?
当前的mergeWith()
签名无法完成。特别是,您正在尝试创建 LinkedHashMap[K,Z]
但没有 Z
输入。获得 Z
的唯一方法是调用 f()
,这需要 X
和 Y
作为传递参数。
因此,如果 xs
是类型 LinkedHashMap[Int,Char]
并且具有元素 (2 -> 'w')
,并且 ys
是类型 LinkedHashMap[Int,Long]
并且具有元素 (8 -> 4L)
,您将如何调用 f(c:Char, l:Long)
以便为键 2
和 8
提供一个 [K,Z]
条目?不可能。
如果可以简化 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
时,这都是一个很好的迹象,表明您的设计需要重新考虑。