Me gustaría escribir un método mergeKeys
que agrupa los valores en un Iterable[(K, V)]
con las teclas. Por ejemplo, podría escribir:Agrupar valores por una clave con cualquier Monoid
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)))
}
}
Sin embargo, me gustaría ser capaz de utilizar cualquier Monoid
en lugar de escribir un método para List
. Por ejemplo, los valores pueden ser enteros y quiero sumarlos en lugar de agregarlos en una lista. O pueden ser tuplas (String, Int)
donde quiero acumular las cadenas en un conjunto, pero agrego los enteros. ¿Cómo puedo escribir tal método? ¿O hay algo más que pueda usar en Scalaz para hacer esto?
Actualización: No estaba tan lejos como pensaba. Me acerqué un poco más, pero sigo sin saber cómo hacerlo funcionar si los valores son tuplas. ¿Debo escribir otra conversión implícita? Es decir, ¿una conversión implícita para cada número de parámetros de tipo?
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
}
Perfecto, gracias! – schmmd