我正在为Map T,T编写我自己的半群。函数的逻辑如下:
如果使用相同的键,则应将值合并到结果映射中。
如果有不同的键,则应将值添加到结果映射中。
我编写了这个函数,但遇到了一个问题:get(key)方法不仅返回T,还返回Option[T]。
解决这个问题的方法是什么?
trait Semigroup[T]:
extension (left: T) def combine(right: T): T
given Semigroup[Int] with
extension (left: Int) def combine(right: Int): Int = ???
given Semigroup[String] with
extension (left: String) def combine(right: String): String = ???
given [T]: Semigroup[List[T]] with
extension (left: List[T]) def combine(right: List[T]): List[T] = ???
given [T: Semigroup]: Semigroup[Map[String, T]] with
extension (left: Map[String, T])
def combine(right: Map[String, T]): Map[String, T] = {
(left.keySet ++ right.keySet) map { key => key -> (summon[Semigroup[T]].combine(left.get(key)) { right.get(key)} ) } toMap
}发布于 2021-05-10 14:33:30
您不想删除选项,这将告诉您如果您需要combine值,因为键在两个映射中;或者其他情况下,只保留值。
(left.keySet | right.keySet).iterator.map { key =>
val value = (left.get(key), right.get(key)) match {
case (Some(v1), Some(v2)) => v1.combine(v2)
case (None, Some(v)) => v
case (Some(v), None) => v
case (None, None) => ??? // Should never happend.
}
key -> value
}.toMap请参见运行https://scastie.scala-lang.org/BalmungSan/VNK8mZKVR7G5uyNPqqzbvQ/12的代码。
发布于 2021-05-10 15:20:01
Option是一件好事:)当键不在地图上时,它保护您不崩溃。
(left.keySet ++ right.keySet)
.map { key => key -> (left.get(key), right.get(key)) }
.flatMap { case (k, (l, r) =>
l.zip(r)
.map { case (x,y) => summon[Semigroup[T]].combine(x)(y)))
.orElse(l)
.orElse(r)
.map(key -> _)
}.toMap或者,为选项创建一个特殊的半群(我不确定scala3语法,但我认为是这样的):
given [T : Semigroup]: Semigroup[Option[T]] with
extension (left: Option[T]) def combine(right: Option[T]): Option[T] =
left.zip(right).map { case(l,r) => summon[Semigroup[T]].combine(l)(r) }
.orElse(l)
.orElse(r)然后你就可以写
(left.keySet ++ right.keySet).map { key =>
key -> summon[Semigroup[Option[T]].combine(left.get(key))(right.get(key))
}发布于 2021-05-10 19:35:09
我只是考虑了一个更好的选择:)您不应该需要显式地处理合并映射键.
(left.toSeq ++ right.toSeq)
.groupMapReduce(_._1)(_._2)(summon[Semigroup[T]].combine(_)(_))groupMapReduce fее有点像黑魔法,但它基本上是groupBy(_.Ь1)、mapValues(_.map(_._2)) (从分组列表中删除键)和reduce(combine) (组合列表中的分组值)的组合。
https://stackoverflow.com/questions/67472227
复制相似问题