Question

val indices: List[Int] = List()
val featValues: List[Double] = List()
for (f <- feat) {
    val q = f.split(':')
    if (q.length == 2) {
        println(q.mkString("\n")) // works fine, displays info
       indices :+ (q(0).toInt)
       featValues :+ (q(1).toDouble)

}
}
println(indices.mkString("\n") + indices.length) // prints nothing and 0?

indices and featValues are not being filled. I'm at a loss here.

Was it helpful?

Solution

You cannot append anything to an immutable data structure such as List stored in a val (immutable named slot).

What your code is doing is creating a new list every time with one element appended, and then throwing it away (by not doing anything with it) — the :+ method on lists does not modify the list in place (even when it's a mutable list such as ArrayBuffer) but always returns a new list.

In order to achieve what you want, the quickest way (as opposed to the right way) is either to use a var (typically preferred):

var xs = List.empty[Int]
xs :+= 123  // same as `xs = xs :+ 123`

or a val containing a mutable collection:

import scala.collection.mutable.ArrayBuffer

val buf = ArrayBuffer.empty[Int]
buf += 123

However, if you really want to make your code idiomatic, you should instead just use a functional approach:

val indiciesAndFeatVals = feat.map { f =>
    val Array(q0, q1) = f.split(':')  // pattern matching in action
    (q0.toInt, q1.toDouble)
}

which will give you a sequence of pairs, which you can then unzip to 2 separate collections:

val (indicies, featVals) = indiciesAndFeatVals.unzip

This approach will avoid the use of any mutable data structures as well as vars (i.e. mutable slots).

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top