首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >当从Map[T,T]获取值时,去掉选项[T]

当从Map[T,T]获取值时,去掉选项[T]
EN

Stack Overflow用户
提问于 2021-05-10 14:23:20
回答 3查看 76关注 0票数 1

我正在为Map T,T编写我自己的半群。函数的逻辑如下:

如果使用相同的键,则应将值合并到结果映射中。

如果有不同的键,则应将值添加到结果映射中。

我编写了这个函数,但遇到了一个问题:get(key)方法不仅返回T,还返回Option[T]

解决这个问题的方法是什么?

代码语言:javascript
复制
  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
      }
EN

回答 3

Stack Overflow用户

回答已采纳

发布于 2021-05-10 14:33:30

您不想删除选项,这将告诉您如果您需要combine值,因为键在两个映射中;或者其他情况下,只保留值。

代码语言:javascript
复制
(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的代码。

票数 1
EN

Stack Overflow用户

发布于 2021-05-10 15:20:01

Option是一件好事:)当键不在地图上时,它保护您不崩溃。

代码语言:javascript
复制
  (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语法,但我认为是这样的):

代码语言:javascript
复制
 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)

然后你就可以写

代码语言:javascript
复制
    (left.keySet ++ right.keySet).map { key =>
       key -> summon[Semigroup[Option[T]].combine(left.get(key))(right.get(key))
     }
票数 1
EN

Stack Overflow用户

发布于 2021-05-10 19:35:09

我只是考虑了一个更好的选择:)您不应该需要显式地处理合并映射键.

代码语言:javascript
复制
    (left.toSeq ++ right.toSeq)
      .groupMapReduce(_._1)(_._2)(summon[Semigroup[T]].combine(_)(_))

groupMapReduce fее有点像黑魔法,但它基本上是groupBy(_.Ь1)mapValues(_.map(_._2)) (从分组列表中删除键)和reduce(combine) (组合列表中的分组值)的组合。

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/67472227

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档