- About Scala
- Documentation
- Code Examples
- Software
- Scala Developers
Best solution to inverse or "pivot" a Map (not swap) ??
Thu, 2011-12-22, 17:44
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
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
Fri, 2011-12-23, 10:31
#2
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
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
Fri, 2011-12-23, 10:41
#3
Re: Best solution to inverse or "pivot" a Map (not swap) ??
Hi Bruno
If you do benchmark, please publish
Tim
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: