2

I have:

val intsPerChar: List[(Char, List[Int])] = List(
  'A' -> List(1,2,3),
  'B' -> List(2,3)
)

I want to get a mapping of ints with the chars that they have a mapping with. ie, I want to get:

val charsPerInt: Map[Int, List[Char]] = Map(
  1 -> List('A'),
  2 -> List('A', 'B'),
  3 -> List('A', 'B')
)

Currently, I am doing the following:

val numbers: List[Int] = l.flatMap(_._2).distinct
numbers.map( n =>
  n -> l.filter(_._2.contains(n)).map(_._1)
).toMap

Is there a less explicit way of doing this? ideally some sort of groupBy.

Maths noob
  • 1,684
  • 20
  • 42

2 Answers2

5

Try

intsPerChar
  .flatMap { case (c, ns) => ns.map((_, c)) }
  .groupBy(_._1)
  .mapValues(_.map(_._2))  
// Map(2 -> List(A, B), 1 -> List(A), 3 -> List(A, B))
Dmytro Mitin
  • 48,194
  • 3
  • 28
  • 66
3

Might be personal preference as to whether you consider it more or less readable, but the following is another option:

intsPerChar
  .flatMap(n => n._2.map(i => i -> n._1)) // List((1,A), (2,A), (3,A), (2,B), (3,B))
  .groupBy(_._1) // Map(2 -> List((2,A), (2,B)), 1 -> List((1,A)), 3 -> List((3,A), (3,B)))
  .transform { (_, v) => v.unzip._2} 

Final output is:

Map(2 -> List(A, B), 1 -> List(A), 3 -> List(A, B))
mforrest
  • 71
  • 3