MrNetroful
MrNetroful

Reputation: 507

ListBuffer from collect func

Hi I'm wordering how could I simplify code below:

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

I hope there is possibility to make this as oneliner.

Upvotes: 0

Views: 73

Answers (3)

Vladimir Matveev
Vladimir Matveev

Reputation: 127791

You can use the to generic conversion method (in Scala <2.13):

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

Using to is similar to breakOut, in the sense that it uses the CanBuildFrom machinery to do the conversion, except here you can provide just the target collection type (without element type) directly to the method. Sadly, this does not work for maps because to requires a type with one type argument (ListBuffer[A], Vector[A], etc), while all Map descendants have two (HashMap[A, B], TreeMap[A, B], etc).

In Scala 2.13 with its new collections library this could be written as follows:

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

Note the round parentheses instead of brackets: in Scala 2.13, the to method accepts a reference to a companion object of a collection rather than collection type. In Scala 2.13, the collection library has different design; in particular, this new approach allows for map types as well:

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

Upvotes: 0

Dima
Dima

Reputation: 40500

Why would you want it a ListBuffer to begin with??? Mutable containers should be avoided, and in scala you almost never need them, except for some rare corner cases. I suggest, that you just pretend they don't exist at all until you get enough grasp of the language to be able to confidently distinguish those rare scenarios.

Having said that, conversion between collection types can be done without intermediaries using a thing called breakOut. This is how you use it:

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

Upvotes: 3

ygor
ygor

Reputation: 1756

Is following simple enough ?

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

If Leaf is a case class:

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

Upvotes: 2

Related Questions