The groupBy method in Lists, Maps, etc., generate a Map after the function.
Is there a way to use the groupBy to generate a Map that preserves insertion order (Link
The following would give you a groupByOrderedUnique method that behaves as you sought. It also adds a groupByOrdered that preserves duplicates as others have asked for in the comments.
import collection.immutable.ListSet
import collection.mutable.{LinkedHashMap => MMap, Builder}
implicit class GroupByOrderedImplicitImpl[A](val t: Traversable[A]) extends AnyVal {
def groupByOrderedUnique[K](f: A => K): Map[K, ListSet[A]] =
groupByGen(ListSet.newBuilder[A])(f)
def groupByOrdered[K](f: A => K): Map[K, List[A]] =
groupByGen(List.newBuilder[A])(f)
def groupByGen[K, C[_]](makeBuilder: => Builder[A, C[A]])(f: A => K): Map[K, C[A]] = {
val map = MMap[K, Builder[A, C[A]]]()
for (i <- t) {
val key = f(i)
val builder = map.get(key) match {
case Some(existing) => existing
case None =>
val newBuilder = makeBuilder
map(key) = newBuilder
newBuilder
}
builder += i
}
map.mapValues(_.result).toMap
}
}
When I use that code like:
import GroupByOrderedImplicit._
val range = 0.until(40)
val in = range ++ range.reverse
println("With dupes:")
in.groupByOrdered(_ % 10).toList.sortBy(_._1).foreach(println)
println("\nUnique:")
in.groupByOrderedUnique(_ % 10).toList.sortBy(_._1).foreach(println)
I get the following output:
With dupes:
(0,List(0, 10, 20, 30, 30, 20, 10, 0))
(1,List(1, 11, 21, 31, 31, 21, 11, 1))
(2,List(2, 12, 22, 32, 32, 22, 12, 2))
(3,List(3, 13, 23, 33, 33, 23, 13, 3))
(4,List(4, 14, 24, 34, 34, 24, 14, 4))
(5,List(5, 15, 25, 35, 35, 25, 15, 5))
(6,List(6, 16, 26, 36, 36, 26, 16, 6))
(7,List(7, 17, 27, 37, 37, 27, 17, 7))
(8,List(8, 18, 28, 38, 38, 28, 18, 8))
(9,List(9, 19, 29, 39, 39, 29, 19, 9))
Unique:
(0,ListSet(0, 10, 20, 30))
(1,ListSet(1, 11, 21, 31))
(2,ListSet(2, 12, 22, 32))
(3,ListSet(3, 13, 23, 33))
(4,ListSet(4, 14, 24, 34))
(5,ListSet(5, 15, 25, 35))
(6,ListSet(6, 16, 26, 36))
(7,ListSet(7, 17, 27, 37))
(8,ListSet(8, 18, 28, 38))
(9,ListSet(9, 19, 29, 39))