Skip to content

Instantly share code, notes, and snippets.

@huynhjl
Created May 1, 2011 15:28
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save huynhjl/950580 to your computer and use it in GitHub Desktop.
Save huynhjl/950580 to your computer and use it in GitHub Desktop.
mapValues on innermost map
// http://stackoverflow.com/questions/5846208/mapvalues-on-innermost-map-of-nested-maps
case class SalesRow(val month:Int, val country:String,
val person:String, val amount:Float)
object Test {
def main(args:Array[String] = null) {
val list = new collection.mutable.ListBuffer[SalesRow]()
for (m <- 1 to 12; p <- List("Joe", "Bill")) {
val i = 2 * (if (p == "Joe") 7 else 13)
list += SalesRow(m, "US", p, i.toFloat + (m.toFloat / 100))
}
for (m <- 1 to 12; p <- List("Jean", "Pierre")) {
val i = 3 * (if (p == "Jean") 11 else 17)
list += SalesRow(m, "FR", p, i.toFloat + (m.toFloat / 100))
}
val seq = list.toSeq
import CanMapInner._
val byCountry = seq.groupBy(_.country)
// how to bring these implicits in scope?
// simple base case (no nesting involved).
implicit def getSimpleMapper[V,B] = new CanMapInner[V,B,V,B] {
def mapInner(in: V, f: (V) => B): B = f(in)
}
// drill down one level of "Map".
implicit def wrappedMapper[K,V,B,InnerV,InnerB](implicit innerMapper: CanMapInner[InnerV,InnerB,V,B]) =
new CanMapInner[Map[K,InnerV], Map[K,InnerB],V,B] {
def mapInner(in: Map[K, InnerV], f: (V) => B): Map[K, InnerB] =
in.mapValues(innerMapper.mapInner(_, f))
}
val byCountryByMonth = deepMapValues(byCountry, (seq:Seq[SalesRow]) => seq.groupBy(_.month))
println(byCountryByMonth)
}
}
// adapter from qmajor:
// http://stackoverflow.com/questions/5846208/mapvalues-on-innermost-map-of-nested-maps/5846633#5846633
// trait to tell us how to map inside of a container.
trait CanMapInner[WrappedV, WrappedB,V,B] {
def mapInner(in: WrappedV, f: V => B): WrappedB
}
object CanMapInner {
// the actual implementation.
def deepMapValues[K,V,B,WrappedV,WrappedB](map: Map[K,WrappedV], f: V => B)
(implicit mapper: CanMapInner[WrappedV,WrappedB,V,B]) = {
map.mapValues(inner => mapper.mapInner(inner, f))
}
}
// vim: set ts=2 sw=2 et:
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment