如何使Scala canBuildFrom构建从Seq到Set的集合类型

时间:2014-05-30 04:43:19

标签: scala scala-collections generic-programming generic-collections

我在Scala上尝试了CanBuildFrom trait,当我尝试自动将Array类型转换为Seq类型时它看起来很好,我认为原因是我们在范围内有CanBuildFrom [Array,T,Seq [T]]。但是,如果我尝试将Array转换为Set,则无法正常工作。此外,将Seq转换为Set也不起作用。我只是想知道我是否应该将相同类型的CanBuildFrom隐式定义为同伴对象来实现转换?如果是,为什么scala默认不提供它,原因是Set是一个函数吗?

以下是Array to Seq

的代码
def transform[U[_]](col: Array[String])(implicit cbf: CanBuildFrom[Array[String], String, U[String]]): U[String] = {
    val builder = cbf()

    for (ele <- col) builder += ele

    builder.result()
  }

CanBuildFromSpec.transform[Seq](Array("123", "3"))

如果我想转换为Array to Set或List,则无法正常工作

CanBuildFromSpec.transform[List](Array("123", "3")) //compilation error, cannot construct
CanBuildFromSpec.transform[Set](Array("123", "3")) //compilation error, cannot construct

1 个答案:

答案 0 :(得分:3)

无需重新发明轮子 - Scala集合具有to[C[_]]方法,可以根据需要进行转换:

scala> List(1, 2, 3).to[Vector]
res0: Vector[Int] = Vector(1, 2, 3)

scala> Array(1, 2, 3).to[Seq]
res1: Seq[Int] = Vector(1, 2, 3)

scala> Seq(1, 2, 3).to[Set]
res2: Set[Int] = Set(1, 2, 3)
BTW,引入CanBuildFrom并非易于转换。需要这样才能使map()filter()等操作保留原始集合类型。

同样Array自动转换为Seq因为CanBuildFrom(这意味着数组内容被复制到新序列中,这可能效率很低),但因为那里是从数组到其包装器的隐式转换,提供Seq接口。