himanshuIIITian
himanshuIIITian

Reputation: 6085

Maintain order in .groupBy() operation of Scala collection

I have the following code snippet:

object Main1 extends App {
  sealed trait XYZ
  {
    def id : String
  }
  class Test() extends XYZ {
    override def id: String = "Test"
  }
  class ABC() extends XYZ {
    override def id: String = "ABC"
  }
  val a: List[XYZ] = List(new Test(), new ABC())
  val b: Map[String, List[XYZ]] = a.groupBy(_.id)
  println(b)

  val c: List[XYZ] = List(new ABC(), new Test())
  val d: Map[String, List[XYZ]] = c.groupBy(_.id)
  println(d)
}

The output is as follows:

Map(Test -> List(Main1$Test@7dc5e7b4), ABC -> List(Main1$ABC@1ee0005))
Map(Test -> List(Main1$Test@3d012ddd), ABC -> List(Main1$ABC@6f2b958e))

How can I maintain the order in the result like in the input collection?

Upvotes: 1

Views: 278

Answers (1)

Andriy Plokhotnyuk
Andriy Plokhotnyuk

Reputation: 7989

If you are not limited to use immutable collections only then it can be easily done with mutable.LinkedHashMap:

import scala.collection.mutable
import scala.collection.mutable.ArrayBuffer

object Main1 extends App {
  sealed trait XYZ
  {
    def id : String
  }
  class Test() extends XYZ {
    override def id: String = "Test"
  }
  class ABC() extends XYZ {
    override def id: String = "ABC"
  }
  val a: List[XYZ] = List(new Test(), new ABC())
  val b: mutable.LinkedHashMap[String, ArrayBuffer[XYZ]] = a.foldLeft(mutable.LinkedHashMap.empty[String, ArrayBuffer[XYZ]]) { (m, x) =>
    m.getOrElseUpdate(x.id, new ArrayBuffer[XYZ]) += x
    m
  }
  println(b)

  val c: List[XYZ] = List(new ABC(), new Test())
  val d: mutable.LinkedHashMap[String, ArrayBuffer[XYZ]] = c.foldLeft(mutable.LinkedHashMap.empty[String, ArrayBuffer[XYZ]]) { (m, x) =>
    m.getOrElseUpdate(x.id, new ArrayBuffer[XYZ]) += x
    m
  }
  println(d)
}

Output maintains the order of the input collection:

LinkedHashMap(Test -> ArrayBuffer(com.github.plokhotnyuk.jsoniter_scala.examples.Main1$Test@56cbfb61), ABC -> ArrayBuffer(com.github.plokhotnyuk.jsoniter_scala.examples.Main1$ABC@1134affc))
LinkedHashMap(ABC -> ArrayBuffer(com.github.plokhotnyuk.jsoniter_scala.examples.Main1$ABC@1b0375b3), Test -> ArrayBuffer(com.github.plokhotnyuk.jsoniter_scala.examples.Main1$Test@2f7c7260))

Upvotes: 1

Related Questions