I have an unordered map:
class O(val a: Int)
Map[String, List[O]]
which I'd like to turn into:
SortedMap[String, SortedMap[Int, O]]
with the child SortedMap keyed on the O field.
I'm sure there must be a more idiomatic code than the below...
class O(val a: Int)
val a: Map[String, List[O]] = Map[String, List[O]]( ("b" -> List(new O(3), new O(2))), "a" -> List(new O(1), new O(2)))
val key1s = a map (_._1)
val oMapsList = ListBuffer[SortedMap[Int, O]]()
for (key1 <- key1s) {
val oList = a(key1)
val key2s = oList map (_.a)
val sortedOMap = SortedMap[Int, O]() ++ (key2s zip oList).toMap
oMapsList += sortedOMap
}
val sortedMap = SortedMap[String, SortedMap[Int, O]]() ++ (key1s zip oMapsList).toMap
Expected sortedMap contents is:
"a" -> ( (1 -> O(1)),(2 -> O(2)) )
"b" -> ( (2 -> O(2)),(2 -> O(3)) )
Firstly, the setup:
scala> case class O(i: Int)
defined class O
scala> Map("a" -> List(O(1), O(2)), "b" -> List(O(2), O(3)))
res0: scala.collection.immutable.Map[java.lang.String,List[O]] = Map(a -> List(O(1), O(2)), b -> List(O(2), O(3)))
Now, import SortedMap
:
scala> import collection.immutable._
import collection.immutable._
Now for the answers!
Use breakOut
- but it involves some unwelcome repetition of types:
scala> res0.map({ case (s, l) => s -> (l.map(o => o.i -> o)(collection.breakOut): SortedMap[Int, O]) })(collection.breakOut): SortedMap[String, SortedMap[Int, O]]
res4: scala.collection.immutable.SortedMap[String,scala.collection.immutable.SortedMap[Int,O]] = Map(a -> Map(1 -> O(1), 2 -> O(2)), b -> Map(2 -> O(2), 3 -> O(3)))
Or a second approach would be to involve a sort
method:
scala> def sort[K: Ordering, V](m: Traversable[(K, V)]) = SortedMap(m.toSeq: _ *)
sort: [K, V](m: scala.collection.immutable.Traversable[(K, V)])(implicit evidence$1: Ordering[K])scala.collection.immutable.SortedMap[K,V]
And so:
scala> sort(res0.mapValues(l => sort(l.map(o => o.i -> o)) ))
res13: scala.collection.immutable.SortedMap[java.lang.String,scala.collection.immutable.SortedMap[Int,O]] = Map(a -> Map(1 -> O(1), 2 -> O(2)), b -> Map(2 -> O(2), 3 -> O(3)))