gpt4 book ai didi

scala - 使用任何 Monoid 通过键对值进行分组

转载 作者:行者123 更新时间:2023-12-04 18:48:38 25 4
gpt4 key购买 nike

我想写一个方法mergeKeys将值分组在 Iterable[(K, V)] 中由 key 。例如,我可以写:

  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, (k, v)) =>
map + (k -> (map(k) |+| v))
}
}
}

implicit def superTraversable[T, U, F[_]](
as: TraversableOnce[(T, F[U])]
): SuperTraversable[T, U, F] =
new SuperTraversable[T, U, 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, (k, v)) =>
map + (k -> (map(k) |+| v))
}
}
}

[...]

现在,对于您的实际问题,无需更改 mergeKeys处理
有趣的组合;只需写一个 Monoid处理任何种类的
结合你想做的事。假设您想做 Strings+Ints 示例:
implicit def monoidStringInt = new Monoid[(String, Int)] {
val zero = ("", 0)
def append(a: (String, Int), 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))

关于scala - 使用任何 Monoid 通过键对值进行分组,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/9713439/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com