Create a map from a collection using the function

I want to create a map from a collection by giving it a mapping function. This is basically equivalent to what a normal method does map

, only I want it to return map

, not a flat collection.

I expect it to have a signature like

def toMap[T, S](T => S): Map[T, S]

      

when called like this

val collection = List(1, 2, 3)
val map: Map[Int, String] = collection.toMap(_.toString + " seconds")

      

the expected value map

would be

Map(1 -> "1 seconds", 2 -> "2 seconds", 3 -> "3 seconds")

      

The method will be equivalent to

val collection = List(1, 2, 3)
val map: Map[Int, String] = collection.map(x => (x, x.toString + " seconds")).toMap

      

is there such a method in Scala?

+3


source to share


2 answers


There is no such single method. As you say, you can use map

and then toMap

. If you are worried about the broker list you create, you can use breakOut

as an implicit second argument for map

:

import scala.collection.breakOut
val map: Map[Int, String] = collection.map(x => (x._1, x._2.toString + " seconds"))(breakOut)

      

You can read more about breakOut

and implicit argument map

here .

This method allows you to create other types, which also have a suitable implementation CanBuildFrom

, without an intermediate step:

val arr: Array[(Int, String)] = collection.map(x => (x._1, x._2.toString + " seconds"))(breakOut)

      



You might also consider using views, which prevent intermediate collections from being created:

val m = (List("A", "B", "C").view map (x => x -> x)).toMap

      

The differences between these approaches are described here .

Finally, there is a method mapValues

that might be suitable for your purposes if you are only matching the values ​​of each key and value pair. Be careful, however, as this method actually returns a view and can lead to unexpected performance results.

+3


source


scalaz has a method fproduct

for Functors

that returns things in the correct form to call .toMap on the result:



scala> import scalaz._,Scalaz._
import scalaz._
import Scalaz._

scala> val collection = List(1, 2, 3)
collection: List[Int] = List(1, 2, 3)

scala> collection.fproduct(_.toString + " seconds").toMap
res0: scala.collection.immutable.Map[Int,String] = Map(1 -> 1 seconds, 2 -> 2 seconds, 3 -> 3 seconds)

      

+3


source







All Articles