Suffix List of Strings with the number of times they were repeated before in Scala

83 Views Asked by At

If we have a List of strings, create a new List where each repeated element has a suffix of the number of times it was repeated, with order preserved.

Example: List("a","a","a","b","b","c","C") should become List("a","a.1","a.2","b","b.1","c","C")

I could loop through each element, update a map that counts the number of times each element is seen, then add each to a List, but there must be more "Scala way" of doing this.

1

There are 1 best solutions below

0
Ivan On

You could write something like this with plain scala using recursive traversal and pattern matching. It's not just scala but a functional way.

val initList = List("a", "a", "a", "b", "b", "c", "C")

@tailrec
def loop(list: List[String], res: Vector[List[String]] = Vector.empty): List[String] = {
  list match {
    case Nil =>
      res.flatMap(_.reverse.zipWithIndex.map { case (str, idx) => if (idx == 0) str else s"$str.$idx" }).toList
    case xs =>
      val (same, rest) = xs.span(_ == xs.head)
      loop(rest, res :+ same)
  }
}

loop(initList) should contain theSameElementsInOrderAs Seq("a", "a.1", "a.2", "b", "b.1", "c", "C")

Or even more elegant with fs2

val initList = List("a", "a", "a", "b", "b", "c", "C")

val result =
  fs2.Stream
    .emits(initList)
    .groupAdjacentBy(identity)
    .map { case (_, groups) => groups }
    .map(_.zipWithIndex.map { case (str, idx) => if (idx == 0) str else s"$str.$idx" })
    .flatMap(fs2.Stream.chunk)
    .toList

result should contain theSameElementsInOrderAs Seq("a", "a.1", "a.2", "b", "b.1", "c", "C")