1

Having

val a: IndexedSeq[String] = Array("one", "two", "three")

def f(s: String): Int = s match {
    case "one" => 1; case "two" => 2; case "three" => 3;
    case _ => throw new IllegalArgumentException
}

how do I best derive

val m: Map[String, Int] = Map("one" -> 1, "two" -> 2, "three" -> 3)

assuming I don't mind introducing a proxy function to return key-value pairs as tuples if this would make a better solution.

PS: I am actually interested in how to map a collection to a collection of a different desired type at all, but have chosen this example as a particular case to illustrate and make the question more specific. This means that the particular case (IndexedSeq to Map) solution is acceptable, but more generic commentaries are welcome. Right now I use foreach populating a mutable map buffer for such cases, but this seems too far from the true Scala functional way IMHO. I find myself using too many of foreach and mutable buffers which makes me nervous and that's why I ask all these questions about mapping.

Ivan
  • 63,011
  • 101
  • 250
  • 382

2 Answers2

6

And what's wrong with:

a map {i => (i, f(i))} toMap

producing:

scala.collection.immutable.Map[String,Int] = Map(one -> 1, two -> 2, three -> 3)
Tomasz Nurkiewicz
  • 334,321
  • 69
  • 703
  • 674
3

This is more efficient but more complicated to fully understand. This avoids the intermediate IndexedSeq[(String, Int)] created by map. Just having fun ;-)

val result: Map[String, Int] = a.map(i => (i, f(i)))(scala.collection.breakOut)

See this SO post: Scala 2.8 breakOut

Community
  • 1
  • 1
schmmd
  • 18,650
  • 16
  • 58
  • 102
  • This is weird: if I don't specify the `val result` type explicitly, it gets `IndexedSeq[(String, Int)]`, but if I do - it works as desired. I am going to study about the bereakOut, thank you for linking to that question. – Ivan Mar 15 '12 at 23:42