List("two", "B"), Map(3 -> List("three", "C"), Map" /> List("two", "B"), Map(3 -> List("three", "C"), Map" /> List("two", "B"), Map(3 -> List("three", "C"), Map"/>

Cats semigroup to merge List of HashMaps into One Scala

668 Views Asked by At

I have a list of hashMaps as follows :

val listHashMaps = List(Map(1 -> List("one", "A") , Map(2 -> List("two", "B"), Map(3 -> List("three", "C"), Map(4 -> List("four", "D")

I want to merge these HashMaps into a single HashMap as :

 Map(1 -> List("one", "A"), 2 -> List("two", "B"), 3 -> List("three", "C", 4 -> List("four", "D")

I have tried

listHashMaps.flatten.ToHashMap but it does not seem to work. and I've read that it is possible to do it using semigroups from cats as follows but I can seem to figure out how to iterate over the List in order to merge the HashMaps into a single one.

val combinedMap = Semigroup[HashMap[Int, List[String]]].combine(aMap, anotherMap)
1

There are 1 best solutions below

0
gogstad On

You can use either use a NonEmptyList and then the default semigroup (which will just concatenate the maps), or you can use the unsafe .reduce function on List.

The reason it's unsafe is that it'll blow up on an empty list. Example:

import cats.data.NonEmptyList

import scala.collection.immutable
import cats.implicits._

object Foo extends App {

  val listHashMaps: List[Map[Int, List[String]]] = List(
    Map(1 -> List("one", "A")),
    Map(2 -> List("two", "B")),
    Map(3 -> List("three", "C")),
    Map(4 -> List("four", "D"))
  )

  val one: Map[Int, List[String]] = listHashMaps.reduce(_ ++ _)

  // safe
  val nonEmpty: NonEmptyList[Map[Int, List[String]]] = NonEmptyList.of(
    Map(1 -> List("one", "A")),
    Map(2 -> List("two", "B")),
    Map(3 -> List("three", "C")),
    Map(4 -> List("four", "D"))
  )

  val two: Map[Int, List[String]] = nonEmpty.reduce

  println(one)
  println(two)
}