Home > front end >  Reverse a Map which has A Set as its value using HOF
Reverse a Map which has A Set as its value using HOF

Time:05-26

I am trying to reverse a map that has a String as the key and a set of numbers as its value

My goal is to create a list that contains a tuple of a number and a list of strings that had the same number in the value set

I have this so far:

def flipMap(toFlip: Map[String, Set[Int]]): List[(Int, List[String])] = {
  toFlip.flatMap(_._2).map(x => (x, toFlip.keys.toList)).toList
}

but it is only assigning every String to every Int

val map = Map(
 "A" -> Set(1,2),
 "B" -> Set(2,3)
)

should produce: List((1, List(A)), (2, List(A, B)), (3, List(B)))

but is producing: List((1, List(A, B)), (2, List(A, B)), (3, List(A, B)))

CodePudding user response:

This works to, but it's not exactly what you might need and you may need some conversions to get the exact data type you need:

toFlip.foldLeft(Map.empty[Int, Set[String]]) {
    case (acc, (key, numbersSet)) =>
      numbersSet.foldLeft(acc) {
        (updatingMap, newNumber) =>
          updatingMap.updatedWith(newNumber) {
            case Some(existingSet) => Some(existingSet   key)
            case None => Some(Set(key))
          }
      }
  }

I used Set to avoid duplicate key insertions in the the inner List, and used Map for better look up instead of the outer List.

CodePudding user response:

// both scala2 & scala3
scala> map.flatten{ case(k, s) => s.map(v => (k, v)) }.groupMapReduce{ case(k, v) => v }{case(k, v) => List(k)}{ _    _ }
val res0: Map[Int, List[String]] = Map(1 -> List(A), 2 -> List(A, B), 3 -> List(B))

// scala3 only
scala> map.flatten((k, s) => s.map(v => (k, v))).groupMapReduce((k, v) => v)((k, v) => List(k))( _    _ )
val res1: Map[Int, List[String]] = Map(1 -> List(A), 2 -> List(A, B), 3 -> List(B))
  • Related