来自 collect 函数的 ListBuffer

ListBuffer from collect func

您好,我正在考虑如何简化以下代码:

val leavesValues: ListBuffer[Double] = ListBuffer()
leavesValues.appendAll(
  leaves
    .collect { case leaf: Leaf => leaf.value.toDouble }
    .toList
)
leavesValues

希望有可能做成单行本

以下是否足够简单?

val leavesValues: ListBuffer[Double] = ListBuffer(leaves.collect { case leaf: Leaf => leaf.value.toDouble } :_*)

如果Leaf是个案class:

val leavesValues: ListBuffer[Double] = ListBuffer(leaves.collect { case Leaf(value) => value.toDouble } :_*)

为什么要以 ListBuffer 开头???应该避免可变容器,在 Scala 中你几乎不需要它们,除了一些罕见的极端情况。我建议您假装它们根本不存在,直到您对语言有足够的掌握,能够自信地区分那些罕见的场景。

话虽如此,集合类型之间的转换可以在没有中介的情况下使用一种叫做 breakOut 的东西来完成。这是你如何使用它:

import scala.collection.breakOut 
val leavesValues: ListBuffer[Double] = leaves.collect { 
  case leaf: Leaf => leaf.value.toDouble
}(breakOut)

您可以使用 to 通用转换方法(在 Scala <2.13 中):

val leavesValues = leaves.collect {
  case leaf: Leaf => leaf.value.toDouble
}.to[ListBuffer]

使用 to 类似于 breakOut,因为它使用 CanBuildFrom 机制来进行转换,除了在这里您可以只提供目标集合类型(没有元素类型)直接传递给方法。可悲的是,这不适用于映射,因为 to 需要一个具有一个类型参数的类型(ListBuffer[A]Vector[A] 等),而所有 Map 后代都有两个(HashMap[A, B]TreeMap[A, B]、等等)。

在 Scala 2.13 及其新的集合库中,可以这样写:

val leavesValues = leaves.collect {
  case leaf: Leaf => leaf.value.toDouble
}.to(ListBuffer)

注意圆括号而不是方括号:在 Scala 2.13 中,to 方法接受对集合而非集合类型的伴生对象的引用。在 Scala 2.13 中,collection 库有不同的设计;特别是,这种新方法还允许使用地图类型:

val map: Map[Int, Int] = List(1 -> 2, 3 -> 4).to(Map)