I am trying to resolve a problem with grouping and summing over scala tuples and maintaining the order of keys.
Say,
val arrayTuples = Array((A, 38) , (B, 150), (B, 250), (B, 890), (D, 600), (C, 515))
to
Map(A -> 38, B -> 1290, D -> 600, C -> 515)
Doing:
val aMap = arrayTuples .groupBy(_._1)
seems to mess with the ordering. Help appreciated.
EDIT: Maintain Ordering of first encountered.
You can use a ListMap
to preserve order, but if you want the left-to-right order-as-encountered, as requested in the comments, some extra steps are needed.
//note the new order of elements
val arrayTuples =
Array(('A', 38), ('B', 150), ('D', 600), ('B', 250), ('C', 515), ('B', 890))
import collection.immutable.ListMap
arrayTuples.foldRight(ListMap[Char,Int]()) {
case ((c,n), lm) => lm.updated(c , lm.getOrElse(c, 0)+n)
}.foldRight(ListMap[Char,Int]()){case (elem,lm) => lm+elem}
//res0: ListMap[Char,Int] = ListMap(A -> 38, B -> 1290, D -> 600, C -> 515)
Because ListMap
preserves the order of last-enountered, which in this case would move the B
entry to the end, I decided to foldRight
, which moves the A
entry to the end, and then foldRight
again to reverse the whole thing.
You can get an insertion ordered map like this:
import scala.collection.immutable.ListMap
val tuples = List(("A", 38) , ("B", 150), ("B", 250), ("B", 890), ("C", 515), ("D", 600))
val initMap = ListMap.empty[String, List[(String, Int)]].withDefaultValue(List.empty)
val aMap = tuples.foldLeft(initMap) { case (acc, (k, v)) =>
val newList = (k -> v) :: acc(k)
acc + (k -> newList)
}
println(aMap) // Map(A -> List((A,38)), B -> List((B,890), (B,250), (B,150)), C -> List((C,515)), D -> List((D,600)))
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With