views:

133

answers:

3

I have a Seq containing objects of a class that looks like this:

class A (val key: Int, ...)

Now I want to convert this Seq to a Map, using the key value of each object as the key, and the object itself as the value. So:

val seq: Seq[A] = ...
val map: Map[Int, A] = ... // How to convert seq to map?

How can I does this efficiently and in an elegant way in Scala 2.8?

+10  A: 

Map over your Seq and produce a sequence of tuples. Then use those tuples to create a Map. Works in all versions of Scala.

val map = Map(seq map { a => a.key -> a }: _*)
Daniel Spiewak
Using `breakOut` as Seth Tisue shows in another answer can make it more efficient by avoiding creating a temporary sequence of tuples.
Jesper
+8  A: 

in Scala 2.8:

val map = seq.map(a => a.key -> a).toMap

or if you're gung ho about avoiding constructing an intermediate sequence of tuples:

val map: Map[Int, A] = seq.map(a => a.key -> a)(collection.breakOut)

Seth Tisue
Thanks. I've seen the `breakOut` thing before but I don't yet know what it is. Time to learn something new again.
Jesper
Found a good explanation of `breakOut` here: http://stackoverflow.com/questions/1715681/scala-2-8-breakout/1716558#1716558
Jesper
+3  A: 

One more 2.8 variation, for good measure, also efficient:

scala> case class A(key: Int, x: Int)
defined class A

scala> val l = List(A(1, 2), A(1, 3), A(2, 1))
l: List[A] = List(A(1,2), A(1,3), A(2,1))

scala> val m: Map[Int, A] = (l, l).zipped.map(_.key -> _)(collection.breakOut)
m: Map[Int,A] = Map((1,A(1,3)), (2,A(2,1)))

Note that if you have duplicate keys, you'll discard some of them during Map creation! You could use groupBy to create a map where each value is a sequence:

scala> l.groupBy(_.key)
res1: scala.collection.Map[Int,List[A]] = Map((1,List(A(1,2), A(1,3))), (2,List(A(2,1))))
retronym