在 Scala 中组合两个具有相同键类型但不同值类型的映射
Combine two Maps with same key type, but different value type in scala
我想合并两个键类型相同但值类型不同的映射。
结果应该包含两种值类型的值(可选,因为某些值可能只存在于一个输入映射中)
类型注释是
def combineMaps[T, U, V](map1: Map[T, U], map2: Map[T, V]): Map[T, (Option[U], Option[V])] = {
???
}
我知道这可以通过复杂的代码来实现,例如:
(map1.mapValues(Some(_) -> None).toList ++ map2.mapValues(None -> Some(_)).toList) // List[(T, (Option[U], Option[V]))]
.groupBy(_._1) // Map[T, List[(T, (Option[U], Option[V]))]]
.mapValues(_.map(_._2)) // Map[T, List[(Option[U], Option[V])]]
.mapValues { list => (
list.collectFirst { case (Some(u), _) => u },
list.collectFirst { case (_, Some(v)) => v }
) } // Map[T, (Option[U], Option[V])]
虽然代码可以运行,但它并没有受益于 Map 中的每个键只出现一次这一事实。方法 .toList
删除此类信息。
我正在寻找一些优雅的 scala 方法来做到这一点(可能有 cats/scalaz,但最好没有它们)
是的 cats 有你介绍过吗,这就是 Align
typeclass 提供的。
您只需要做:
m1.align(m2)
这将 return 一个 Map[T, Ior[U, V]]
比一对 Options
更好,因为 Ior
保留了两个元素中至少一个必须存在的事实。
keySet
的联合,然后将键映射到 get
的元组应该这样做:
def combineMaps[T, U, V](m1: Map[T, U], m2: Map[T, V]): Map[T, (Option[U], Option[V])] =
(m1.keySet union m2.keySet).map(k => (k, (m1.get(k), m2.get(k)))).toMap
示例:
combineMaps(Map('a'->1, 'b'->2, 'c'->3), Map('a'->10.0, 'c'->30.0, 'd'->40.0))
// res1: Map[Char,(Option[Int], Option[Double])] = Map(
// a -> (Some(1),Some(10.0)), b -> (Some(2),None), c -> (Some(3),Some(30.0)), d -> (None,Some(40.0))
// )
我想合并两个键类型相同但值类型不同的映射。
结果应该包含两种值类型的值(可选,因为某些值可能只存在于一个输入映射中)
类型注释是
def combineMaps[T, U, V](map1: Map[T, U], map2: Map[T, V]): Map[T, (Option[U], Option[V])] = {
???
}
我知道这可以通过复杂的代码来实现,例如:
(map1.mapValues(Some(_) -> None).toList ++ map2.mapValues(None -> Some(_)).toList) // List[(T, (Option[U], Option[V]))]
.groupBy(_._1) // Map[T, List[(T, (Option[U], Option[V]))]]
.mapValues(_.map(_._2)) // Map[T, List[(Option[U], Option[V])]]
.mapValues { list => (
list.collectFirst { case (Some(u), _) => u },
list.collectFirst { case (_, Some(v)) => v }
) } // Map[T, (Option[U], Option[V])]
虽然代码可以运行,但它并没有受益于 Map 中的每个键只出现一次这一事实。方法 .toList
删除此类信息。
我正在寻找一些优雅的 scala 方法来做到这一点(可能有 cats/scalaz,但最好没有它们)
是的 cats 有你介绍过吗,这就是 Align
typeclass 提供的。
您只需要做:
m1.align(m2)
这将 return 一个 Map[T, Ior[U, V]]
比一对 Options
更好,因为 Ior
保留了两个元素中至少一个必须存在的事实。
keySet
的联合,然后将键映射到 get
的元组应该这样做:
def combineMaps[T, U, V](m1: Map[T, U], m2: Map[T, V]): Map[T, (Option[U], Option[V])] =
(m1.keySet union m2.keySet).map(k => (k, (m1.get(k), m2.get(k)))).toMap
示例:
combineMaps(Map('a'->1, 'b'->2, 'c'->3), Map('a'->10.0, 'c'->30.0, 'd'->40.0))
// res1: Map[Char,(Option[Int], Option[Double])] = Map(
// a -> (Some(1),Some(10.0)), b -> (Some(2),None), c -> (Some(3),Some(30.0)), d -> (None,Some(40.0))
// )