Ashiqur Rahman
Ashiqur Rahman

Reputation: 29

Scala Compare Map value to another Map key

I have two Maps:

val myMap1 = Map(
    testKey1 -> List(testValue1, testValue2, testValue3....), 
    testKey2 -> List(testValue4, testValue5, testValue6....),
    testKey3 -> List(testValue7, testValue8, testValue9....)     
    testKey4 -> List(testValue10, testValue11, testValue12....)     
)

val myMap2 = Map(
        testValue1 -> List(Value1, Value2, Value3....), 
        testValue5 -> List(Value4, Value5, Value6....),
        testValue10 -> List(Value7, Value8, Value9....)
    )

And I wanted to create a third Map by matching Map1 values to Map2 Keys,

Where Map1 keys will be the Key and Map2 values will be the value of this new third Map.

It would be like this

val myMap3 = Map(
        testKey1 -> List(Value1, Value2, Value3....), 
        testKey2 -> List(Value4, Value5, Value6....),
        testKey4 -> List(Value7, Value8, Value9....)
    )

I am failed to iterate over the Map1 values which is a list and get the corresponding key of that value.

Upvotes: 0

Views: 1339

Answers (1)

You can get what you want by using mapValues on the first Map to get each List of values' keys, and then use flatMap on this lis to get the desired values.
Here is an example, please note the getOrElse method, to ensure we always get a value, even if the key does not exists.

val myMap1 = Map(
  "testKey1" -> List("testValue1", "testValue2", "testValue3"), 
  "testKey2" -> List("testValue4", "testValue5", "testValue6"),
  "testKey3" -> List("testValue7", "testValue8", "testValue9"),
  "testKey4" -> List("testValue10", "testValue11", "testValue12")     
)

val myMap2 = Map(
  "testValue1" -> List(1, 2, 3), 
  "testValue2" -> List(5), 
  "testValue5" -> List(4, 5, 6),
  "testValue10" -> List(7, 8, 9)
)

val myMap3 = myMap1.mapValues {
  valuesList => valuesList.flatMap {
    valueKey => myMap2.getOrElse(valueKey, List.empty[Int])
  }
}

// myMap3: Map[String, List[Int]] = Map(
//   testKey1 -> List(1, 2, 3, 5),
//   testKey2 -> List(4, 5, 6),
//   testKey3 -> List(),
//   testKey4 -> List(7, 8, 9)
// )

If you need to remove the keys with empty values you can filter after.
myMap3.filter { case (_, values) => values.nonEmpty }

Edit

If I want to create this myMap3 where the value will be myMap2's key and their respective value.

Given the values of myMap1 are a list of keys for myMap2, I think what you really want is a Map[String, Map[String, List[A]].

val myMap4 = myMap1.mapValues {
  valuesList => valuesList.map {
    valueKey => valueKey -> myMap2.getOrElse(valueKey, List.empty[Int])
  }.toMap
}

// myMap4: Map[String, Map[String, List[Int]]] = Map(
//   testKey1 -> Map(testValue1 -> List(1, 2, 3), testValue2 -> List(5), testValue3 -> List()),
//   testKey2 -> Map(testValue4 -> List(), testValue5 -> List(4, 5, 6), testValue6 -> List()),
//   testKey3 -> Map(testValue7 -> List(), testValue8 -> List(), testValue9 -> List()),
//   testKey4 -> Map(testValue10 -> List(7, 8, 9), testValue11 -> List(), testValue12 -> List())
// )

Again, you can filter empty values if you don't need them.

val myMap5 = myMap1.mapValues {
  valuesList => valuesList.flatMap { // here we use flatMap, to filter any None.
    valueKey => myMap2.get(valueKey).map(values => valueKey -> values)
  }.toMap
} filter {
  case (_, values) => values.nonEmpty
}

// myMap5: Map[String, Map[String, List[Int]]] = Map(
//   testKey1 -> Map(testValue1 -> List(1, 2, 3), testValue2 -> List(5)),
//   testKey2 -> Map(testValue5 -> List(4, 5, 6)),
//   testKey4 -> Map(testValue10 -> List(7, 8, 9))
// )

Upvotes: 2

Related Questions