加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 综合聚焦 > 服务器 > 安全 > 正文

scala – 使用任何Monoid的键对值进行分组

发布时间:2020-12-16 18:18:13 所属栏目:安全 来源:网络整理
导读:我想编写一个方法mergeKeys,它通过键对Iterable [(K,V)]中的值进行分组.例如,我可以写: def mergeKeysList[K,V](iter: Iterable[(K,V)]) = { iter.foldLeft(Map[K,List[V]]().withDefaultValue(List.empty[V])) { case (map,(k,v)) = map + (k - (v :: map(
我想编写一个方法mergeKeys,它通过键对Iterable [(K,V)]中的值进行分组.例如,我可以写:

def mergeKeysList[K,V](iter: Iterable[(K,V)]) = {
     iter.foldLeft(Map[K,List[V]]().withDefaultValue(List.empty[V])) {
        case (map,(k,v)) =>
          map + (k -> (v :: map(k)))
     }
  }

但是,我希望能够使用任何Monoid而不是为List编写方法.例如,值可能是整数,我想要对它们求和,而不是将它们附加到列表中.或者它们可能是元组(String,Int),我想在集合中累积字符串但添加整数.我怎么写这样的方法?或者还有什么我可以在scalaz中使用它来完成这项工作?

更新:我没有想象的那么遥远.我有点接近,但如果值是元组,我仍然不知道如何使它工作.我是否需要编写另一个隐式转换?即,每个类型参数的一个隐式转换?

sealed trait SuperTraversable[T,U,F[_]]
extends scalaz.PimpedType[TraversableOnce[(T,F[U])]] {
  def mergeKeys(implicit mon: Monoid[F[U]]): Map[T,F[U]] = {
    value.foldLeft(Map[T,F[U]]().withDefaultValue(mon.zero)) {
      case (map,v)) =>
        map + (k -> (map(k) |+| v))
    }
  }
}

implicit def superTraversable[T,F[_]](
  as: TraversableOnce[(T,F[U])]
): SuperTraversable[T,F] = 
    new SuperTraversable[T,F] {
      val value = as
    }

解决方法

首先,虽然它与您的问题无关,但您限制了代码
通过明确提到类型构造函数F [_].它工作正常
没有这样做:

sealed trait SuperTraversable[K,V]
extends scalaz.PimpedType[TraversableOnce[(K,V)]] {
    def mergeKeys(implicit mon: Monoid[V]): Map[K,V] = {
        value.foldLeft(Map[K,V]().withDefaultValue(mon.zero)) {
            case (map,v)) =>
                map + (k -> (map(k) |+| v))
        }
    }
}

[...]

现在,对于您的实际问题,没有必要更改mergeKeys来处理
有趣的组合;只需写一个Monoid来处理任何类型的
结合你想做的事.假设你想做你的Strings Ints示例:

implicit def monoidStringInt = new Monoid[(String,Int)] {
    val zero = ("",0)
    def append(a: (String,b: => (String,Int)) = (a,b) match {
        case ((a1,a2),(b1,b2)) => (a1 + b1,a2 + b2)
    }
}

println {
    List(
        "a" -> ("Hello,",20),"b" -> ("Goodbye,30),"a" -> ("World",12)
    ).mergeKeys
}

Map(a -> (Hello,World,32),b -> (Goodbye,30))

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读