【问题标题】:how to make Scala canBuildFrom to build collection type from Seq to Set如何使 Scala canBuildFrom 构建从 Seq 到 Set 的集合类型
【发布时间】:2014-07-19 18:37:36
【问题描述】:

我在 Scala 上对 CanBuildFrom 特征进行了实验,当我尝试将 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"))

如果我想转换为数组来设置或列表,它不起作用

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

【问题讨论】:

  • 您可以将collection.breakOut 作为CanBuildFrom 提供给您的transform,以允许您构建任何集合(至少可以包含字符串的任何集合)。或者您可以声明所需类型的隐式CanBuildFrom

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


【解决方案1】:

没有必要重新发明轮子 - 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)

顺便说一句,CanBuildFrom 的引入不是为了方便兑换。为了让map()filter() 等操作保留原始集合类型,需要它。

Array 也自动转换为Seq,这不是因为CanBuildFrom(这意味着将数组内容复制到新序列中,这可能效率很低),而是因为存在从数组的隐式转换到他们提供Seq 接口的包装器。

【讨论】:

  • 感谢您的评论,我知道“to”可以做一些事情,但是 CanBuildForm 对于 Collection 上的泛型编程非常有用。例如,如果我想在集合上申请计算逻辑,又不想为不同的集合重复函数,CanBuildForm 是一个不错的选择。因此,在这种情况下,“asInstanceof”或“to”不是我想要的。
猜你喜欢
  • 1970-01-01
  • 2012-08-25
  • 1970-01-01
  • 2015-10-09
  • 2017-05-17
  • 2018-06-29
  • 2017-04-13
  • 1970-01-01
  • 2022-12-18
相关资源
最近更新 更多