使用函数从集合创建映射

时间:2014-12-16 23:38:27

标签: scala scala-collections

我想通过为集合提供映射功能来创建集合。它基本上等同于普通map方法所做的,只是我希望它返回Map,而不是平面集合。

我希望它有像

这样的签名
def toMap[T, S](T => S): Map[T, S]

像这样调用

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

map的预期值为

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

该方法等同于

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

Scala中有这样的方法吗?

2 个答案:

答案 0 :(得分:3)

没有这样的单一方法。如您所说,您可以使用map后跟toMap。如果您担心要创建的中间列表,可以考虑使用breakOut作为map的隐式第二个参数:

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

您可以详细了解breakOut以及map here的隐含参数。

此方法允许您构建具有合适CanBuildFrom实现的其他类型,而无需中间步骤:

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

您可能还想考虑使用禁止创建中间集合的视图:

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

描述了这些方法之间的差异here

最后,如果您只映射每个键值对的值,则可以使用mapValues方法,它可能适合您的用途。但要小心,因为此方法实际上会返回一个视图,并可能导致意外的性能命中。

答案 1 :(得分:3)

scalaz对fproduct有一个Functors方法,它返回正确形状的东西,用于在结果上调用.toMap:

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)