- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Traversable.groupBy - why is this not defined in terms of a "That" target collection
Tue, 2010-04-27, 18:18
The groupBy method is hard-coded to result in an immutable.Map but I would like to have something which can be configurable via a MapCanBuildFrom, perhaps this could be called groupInto. (I further think that a MultiMapCanBuildFrom should be supplied as part of the standard API.)
I'm hardly the best with higher-kinded types but the following seems to work. If there's a better way, I'd love to know:
implicit def MultiMapCanBuildFrom[From, Elem, K, V](implicit ev: Elem <:< (K, V)) = new CanBuildFrom[From, Elem, MultiMap[K, V]] { def apply() : Builder[Elem, MultiMap[K, V]] = new Builder[Elem, MultiMap[K, V]] { val mm: MultiMap[K, V] = new mutable.HashMap[K, mutable.Set[V]]() with MultiMap[K, V] def +=(elem : Elem) = { val (k, v) : (K, V) = elem; mm.addBinding(k, v); this } def clear() = mm.clear() def result = mm }
def apply(from : From) : Builder[Elem, MultiMap[K, V]] = apply() }
I can then do the following directly:
scala> val l = List("Hello", "World", "Feel") l: List[java.lang.String] = List(Hello, World, Feel)
scala> import collection.breakOut import collection.breakOut
scala> l.map(i => i.length -> i)(breakOut) : collection.mutable.MultiMap[Int, String] res0: scala.collection.mutable.MultiMap[Int,String] = Map((4,Set(Feel)), (5,Set(Hello, World)))
The groupInto functionality can then be provided something like:
def groupInto[A, K, That](f : A => K)(implicit bf: CanBuildFrom[Repr, (K, A), That] ) : That = { val b = bf(repr) for (a <- this) b += (f(a) -> a) b.result }
Because I can't actually add this method to TraversableLike, I can't quite figure out whether it would work. I'd want to be able to get a MultiMap[K, A] or a Map[K, Repr] back dependent on typing hints.
Is this something worthy of addition into TraversableLike?
Chris
Get a free e-mail account with Hotmail. Sign-up now.
I'm hardly the best with higher-kinded types but the following seems to work. If there's a better way, I'd love to know:
implicit def MultiMapCanBuildFrom[From, Elem, K, V](implicit ev: Elem <:< (K, V)) = new CanBuildFrom[From, Elem, MultiMap[K, V]] { def apply() : Builder[Elem, MultiMap[K, V]] = new Builder[Elem, MultiMap[K, V]] { val mm: MultiMap[K, V] = new mutable.HashMap[K, mutable.Set[V]]() with MultiMap[K, V] def +=(elem : Elem) = { val (k, v) : (K, V) = elem; mm.addBinding(k, v); this } def clear() = mm.clear() def result = mm }
def apply(from : From) : Builder[Elem, MultiMap[K, V]] = apply() }
I can then do the following directly:
scala> val l = List("Hello", "World", "Feel") l: List[java.lang.String] = List(Hello, World, Feel)
scala> import collection.breakOut import collection.breakOut
scala> l.map(i => i.length -> i)(breakOut) : collection.mutable.MultiMap[Int, String] res0: scala.collection.mutable.MultiMap[Int,String] = Map((4,Set(Feel)), (5,Set(Hello, World)))
The groupInto functionality can then be provided something like:
def groupInto[A, K, That](f : A => K)(implicit bf: CanBuildFrom[Repr, (K, A), That] ) : That = { val b = bf(repr) for (a <- this) b += (f(a) -> a) b.result }
Because I can't actually add this method to TraversableLike, I can't quite figure out whether it would work. I'd want to be able to get a MultiMap[K, A] or a Map[K, Repr] back dependent on typing hints.
Is this something worthy of addition into TraversableLike?
Chris
Get a free e-mail account with Hotmail. Sign-up now.