【发布时间】:2019-01-05 11:39:55
【问题描述】:
您好,我在说如何简化下面的代码:
val leavesValues: ListBuffer[Double] = ListBuffer()
leavesValues.appendAll(
leaves
.collect { case leaf: Leaf => leaf.value.toDouble }
.toList
)
leavesValues
我希望有可能把它做成一个单行线。
【问题讨论】:
您好,我在说如何简化下面的代码:
val leavesValues: ListBuffer[Double] = ListBuffer()
leavesValues.appendAll(
leaves
.collect { case leaf: Leaf => leaf.value.toDouble }
.toList
)
leavesValues
我希望有可能把它做成一个单行线。
【问题讨论】:
为什么要以ListBuffer 开头???应该避免使用可变容器,在 scala 中你几乎不需要它们,除了一些罕见的极端情况。我建议,在您充分掌握该语言以能够自信地区分这些罕见场景之前,您只需假装它们根本不存在。
话虽如此,集合类型之间的转换可以在没有中介的情况下使用称为breakOut 的东西完成。这就是你使用它的方式:
import scala.collection.breakOut
val leavesValues: ListBuffer[Double] = leaves.collect {
case leaf: Leaf => leaf.value.toDouble
}(breakOut)
【讨论】:
list::value。更多here
breakout。但是,我也建议编辑答案。首先,让他拥有他的ListBuffer,然后解释为什么这可能不是最好的收藏。 ??? 也可以替换为 ?。
关注够简单吗?
val leavesValues: ListBuffer[Double] = ListBuffer(leaves.collect { case leaf: Leaf => leaf.value.toDouble } :_*)
如果Leaf 是一个案例类:
val leavesValues: ListBuffer[Double] = ListBuffer(leaves.collect { case Leaf(value) => value.toDouble } :_*)
【讨论】:
你可以使用to泛型转换方法(在Scala
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 中,集合库有不同的设计;特别是,这种新方法还允许使用地图类型:
val map: Map[Int, Int] = List(1 -> 2, 3 -> 4).to(Map)
【讨论】: