Suppose I have a list of tuples List[(A, B)]
. What is the best way to convert it to a multimap
, which maps A
to Set[B]
? Can I build an immutable multimap
?
Asked
Active
Viewed 1.1k times
2 Answers
22
Can I build an immutable multimap ?
Not with the MultiMap
in Scala standard library. Of course, you can write your own.
What is the best way to convert it to a multimap?
import scala.collection.mutable.{HashMap, Set, MultiMap}
def list2multimap[A, B](list: List[(A, B)]) =
list.foldLeft(new HashMap[A, Set[B]] with MultiMap[A, B]){(acc, pair) => acc.addBinding(pair._1, pair._2)}

Alexey Romanov
- 167,066
- 35
- 309
- 487
19
I'm a bit confused, Multimap
doesn't map A
to Set[B]
, it maps A
to B
where B
can have many values. Since you want something immutable, I'm going to change this to Map[A, Set[B]]
which isn't a Multimap
but does one of the things you said you wanted.
// This is your list of (A, B)
val l = List((1, "hi"),
(2, "there"),
(1, "what's"),
(3, "up?"))
// Group it and snip out the duplicate 'A'
// i.e. it initially is Map[A, List[(A, B)]] and we're going to convert it
// to Map[A, Set[B]]
val m = l.groupBy(e => e._1).mapValues(e => e.map(x => x._2).toSet)
println(m)
// Prints: Map(3 -> Set(up?), 1 -> Set(hi, what's), 2 -> Set(there))

Derek Wyatt
- 2,697
- 15
- 23
-
6You can also use `mapValues`, which won't actually produce a new collection, but will act as a mapped `view` on values. – Daniel C. Sobral Aug 26 '11 at 20:12
-
1`mapValues` - nice. I've never used that one before. Updated to use that instead. – Derek Wyatt Aug 26 '11 at 20:18
-
7cleaner still: `val m = l groupBy (_._1) mapValues (_ map {_._2} toSet)` – Kevin Wright Aug 26 '11 at 23:14
-
5That's not cleaner, it's just less characters. – myyk Sep 27 '12 at 01:24
-
1mapValues means an overhead every time a lookup is performed. A workaround is to do .map(identity). Credit tpolecat and referer on #scala – malaverdiere Mar 21 '14 at 02:31
-
2Use map directly: `list.groupBy(_._1).map{case(x, xs) => (x, xs.map(_._2))}` – r0estir0bbe Jul 07 '15 at 20:34