在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)