This page is no longer maintained — Please continue to the home page at www.scala-lang.org

Best solution to inverse or "pivot" a Map (not swap) ??

3 replies
BrunoVernay
Joined: 2010-07-28,
User offline. Last seen 1 year 25 weeks ago.
Hello
I have a structure like this: 
case class Bookmark( url: String, labels: Set[String])
val myb = Set( Bookmark("U-A",Set("L-1")),  Bookmark("U-B", Set("L-2")),  Bookmark("U-C", Set("L-3")),  Bookmark("U-D", Set("L-1", "L-3")),  Bookmark("U-E", Set("L-1")))
and I would like to get my bookmarks by labels, like this: Map[String, Set[Bookmark]]
I came up with two solutions:var oMap = Map[String, Set[Bookmark]]()for ( bk <- myb ; lab <- bk.labels ) {  if (oMap.contains(lab))    oMap = oMap.updated( lab, oMap(lab) +  bk )  else    oMap = oMap + ( lab -> Set(bk) )}
and
case class LB( label: String,  bkm:Bookmark)val a1 = for (bk <- myb; lab <- b.labels ) yield LB(lab, bk)
val a2 = a1 groupBy(_.label) mapValues( _ map(_.bkm) )
both gives the same result, but the solution with the mutable Map looks easier. Is there a third better way ?
Here is the result:Map(  L-3 -> Set( Bookmark( U-C, Set(L-3)), Bookmark( U-D,Set(L-1, L-3))),  L-1 -> Set( Bookmark( U-E, Set(L-1)), Bookmark( U-A,Set(L-1)), Bookmark( U-D,Set(L-1, L-3))),  L-2 -> Set( Bookmark( U-B, Set(L-2))))
RegardsBruno
Joshua.Suereth
Joined: 2008-09-02,
User offline. Last seen 32 weeks 5 days ago.
Re: Best solution to inverse or "pivot" a Map (not swap) ??

Myb flatMap { b => b.labels map ((b,_)) } groupBy (_._2) mapValues ... something ....

On Dec 22, 2011 11:44 AM, "Bruno Vernay" <brunovern.a@gmail.com> wrote:
Hello
I have a structure like this: 
case class Bookmark( url: String, labels: Set[String])
val myb = Set( Bookmark("U-A",Set("L-1")),  Bookmark("U-B", Set("L-2")),   Bookmark("U-C", Set("L-3")),  Bookmark("U-D", Set("L-1", "L-3")),   Bookmark("U-E", Set("L-1")))
and I would like to get my bookmarks by labels, like this: Map[String, Set[Bookmark]]
I came up with two solutions:var oMap = Map[String, Set[Bookmark]]()for ( bk <- myb ; lab <- bk.labels ) {   if (oMap.contains(lab))    oMap = oMap.updated( lab, oMap(lab) +  bk )  else     oMap = oMap + ( lab -> Set(bk) )}
and
case class LB( label: String,  bkm:Bookmark)val a1 = for (bk <- myb; lab <- b.labels ) yield LB(lab, bk)
val a2 = a1 groupBy(_.label) mapValues( _ map(_.bkm) )
both gives the same result, but the solution with the mutable Map looks easier. Is there a third better way ?
Here is the result:Map(  L-3 -> Set( Bookmark( U-C, Set(L-3)), Bookmark( U-D,Set(L-1, L-3))),   L-1 -> Set( Bookmark( U-E, Set(L-1)), Bookmark( U-A,Set(L-1)), Bookmark( U-D,Set(L-1, L-3))),  L-2 -> Set( Bookmark( U-B, Set(L-2))))
RegardsBruno
BrunoVernay
Joined: 2010-07-28,
User offline. Last seen 1 year 25 weeks ago.
Re: Best solution to inverse or "pivot" a Map (not swap) ??
OK looks like it could replace the loop in my second solution:case class LB( label: String,  bkm:Bookmark)val a1 = myb flatMap { bk => bk.labels map ( LB( _, bk) ) }  // for (bk <- myb; lab <- b.labels ) yield LB(lab, bk)
val a2 = a1 groupBy(_.label) mapValues( _ map(_.bkm) )
This was what I was searching for, thanks. I didn't think about exploding the bookmarks within the flatMap.
But then I am a bit frightened about all the operation it implies compared to the use of a mutable Map. I guess I should simply do some benchmark.Ideally,  myb groupByFlat( _.labels )  would do the trick, but I guess there are already too many functions in the collections
Bruno
Tim P
Joined: 2011-07-28,
User offline. Last seen 1 year 4 weeks ago.
Re: Best solution to inverse or "pivot" a Map (not swap) ??

Hi Bruno
If you do benchmark, please publish
Tim

Copyright © 2012 École Polytechnique Fédérale de Lausanne (EPFL), Lausanne, Switzerland