Should I create a new object for blending in a Scala line?

In Scala, calling groupBy() on a collection returns a Map , where the values ​​are collections, but I want a MultiMap . What is the easiest way to do the conversion? Can I avoid creating a new MultiMap and copying everything?

+6
scala traits
source share
1 answer

I think the answer to the question is: β€œShould I create a new object for blending in the Scala line?” Yes. "You can minimize pain with wrapping objects and implicit conversions.


For your specific problem, I could not force groupBy (...) to return the volatile map to mutable sets that you would need to wrap using "MapProxy with MultiMap". But not too many lines of code to implement your own version of "groupBy":

 package blevins.example object App extends Application { implicit def multiMapable[B](c: Iterable[B]) = new { def groupByMM[A](f: B => A) = { import scala.collection.mutable._ val ret = new HashMap[A,Set[B]] with MultiMap[A,B] for (e <- c) { ret.addBinding(f(e), e) } ret } } val c = List(1,2,3,4,5,6,7,8,9) val mm = c.groupByMM { i => if (i < 5) "alpha" else "beta" } mm.addBinding("alpha",12) println(mm) // Map(beta -> Set(5, 7, 6, 9, 8), alpha -> Set(3, 1, 4, 2, 12)) } 

Adding

The following is an example of transferring an existing Map [String, Set [Int]] to MultiMap without copying the values:

 object App extends Application { import scala.collection.mutable._ val seed: Map[String,Set[Int]] = Map("even" -> Set(2,4,6), "odd" -> Set(1,3,5)) val multiMap = new MapProxy[String,Set[Int]] with MultiMap[String,Int] { val self = seed } multiMap.addBinding("even", 8) println(multiMap) // Map(odd -> Set(5, 3, 1), even -> Set(6, 8, 4, 2)) } 

Note that this cannot be done from the result of groupBy (...), because the seed map must be mutable, and groupBy (...) returns an immutable map.

+5
source share

All Articles