在Scala中的filter,地图,flatMap期间如何轻松地将一个集合types转换为另一个集合types?

假设我有一个List[Int] ,并且我想在每个元素上调用toString ,并将结果作为Vector[String]

斯卡拉有什么不同的方式来做到这一点? 是否有一个解决scheme与最小量的显式打字? – 即,我想指定我想要一个Vector而不是一个List ,但我想从过滤函数推断String参数。

还是应该显式传递一个CanBuildFrom实例? 我从哪里得到这些 – 对于Seq s, Set s和Map s?

使用breakOut

使用breakOut作为CanBuildFrom ,让CanBuildFrom知道你想要的结果types是什么(不幸的是你需要在这里指定String)

 scala> import collection.breakOut import collection.breakOut scala> List(1, 2, 3) res0: List[Int] = List(1, 2, 3) scala> res0.map(_.toString)(breakOut) : Vector[String] res2: Vector[String] = Vector(1, 2, 3) 

使用[Collection](从Scala 2.10.0开始)

Scala 2.10.0引入了一个简单的方法来将一个集合转换为另一个集合:

 scala> List(1, 2, 3).map(_.toString).to[Vector] res0: Vector[String] = Vector(1, 2, 3) 

使用toIndexedSeq

或者明确要求一个IndexedSeq

 scala> res0.map(_.toString).toIndexedSeq res4: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3) 

如果您想要在不创build中间List情况下执行此操作,则:

 scala> res0.view.map(_.toString).toIndexedSeq res5: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3) 

使用自然转换

你可以做到这一点(笨拙,但更普遍)使用自然转换

 scala> trait Trans[F[_], G[_]] { | def f2g[A](f : F[A]) : G[A] | } defined trait Trans 

现在从List〜> Vector转换中提供一个types实例:

 scala> implicit val List2Vector = new Trans[List, collection.immutable.Vector] { | def f2g[A](l : List[A]) : Vector[A] = l.map(identity[A])(collection.breakOut) | } List2Vector: java.lang.Object with Trans[List,scala.collection.immutable.Vector] = $anon$1@56329755 

定义一个包装器和一个隐式转换:

 scala> class Clever[M[_], A](ma : M[A]) { def to[N[_]](implicit t : Trans[M, N]) : N[A] = t.f2g(ma) } defined class Clever scala> implicit def ma2clever[M[_], A](ma : M[A]) = new Clever[M, A](ma) ma2clever: [M[_],A](ma: M[A])Clever[M,A] 

然后:

 scala> List(1, 2, 3).map(_.toString).to[Vector] res4: Vector[java.lang.String] = Vector(1, 2, 3)