在Scala中的filter、map、flatMap期间,如何轻松地从一种集合类型转换为另一种集合类型?

在Scala中的filter、map、flatMap期间,如何轻松地从一种集合类型转换为另一种集合类型?,scala,collections,map,filter,implicit-conversion,Scala,Collections,Map,Filter,Implicit Conversion,假设我有一个列表[Int],我想对每个元素调用toString,并将结果作为向量[String]返回 在Scala中实现这一点的各种方法有哪些?是否有一种只需最少显式键入的解决方案?-i、 例如,我想指定我想要一个向量而不是列表,但是我希望从filter函数中推断字符串参数 或者我应该显式地传递一个CanBuildFrom实例吗?我从哪里获得这些信息?对于Seqs、Sets和Maps,使用breakOut 使用breakOut作为CanBuildFrom并让打字机知道您想要的结果类型(不幸的是,

假设我有一个
列表[Int]
,我想对每个元素调用
toString
,并将结果作为
向量[String]
返回

在Scala中实现这一点的各种方法有哪些?是否有一种只需最少显式键入的解决方案?-i、 例如,我想指定我想要一个
向量
而不是
列表
,但是我希望从filter函数中推断
字符串
参数

或者我应该显式地传递一个
CanBuildFrom
实例吗?我从哪里获得这些信息?对于
Seq
s、
Set
s和
Map
s,使用breakOut 使用
breakOut
作为
CanBuildFrom
并让打字机知道您想要的结果类型(不幸的是,您需要在此处指定字符串)


用于[收集](从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 或者,明确要求使用
索引eq

scala> res0.map(_.toString).toIndexedSeq
res4: scala.collection.immutable.IndexedSeq[String] = Vector(1, 2, 3)
如果要在不创建中间
列表的情况下执行此操作,则:

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

使用自然变换 您可以使用自然变换来完成(笨拙,但更一般)

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

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]
然后:


谢谢,使用
breakOut
似乎对
map
flatMap
很有效,但不适用于
过滤器,后者不接受
CanBuildFrom
。我可以使用
向量
使用
索引eq
,但是如果我想要一个任意的集合,该集合可以使用
构建,该怎么办?我必须经历自然转换吗?@JPP-我想这取决于你的用例。就我个人而言,我不会使用自然转换-似乎是一个没有太多收获的痛苦。另外,为什么集合类型的标准形式(例如,
IndexedSeq
Vector
)不够好?我同意,标准形式通常足够好,与视图一起,我们避免创建中间表示。我只是好奇是否有办法做到这一点。我会把问题留一段时间,如果没有其他问题,我会接受你的回答。@JPP
filter
无法返回其他集合。@DanielC.Sobral或oxbow_lakes,在2.10中有更好的方法吗?更新答案是否值得?
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)