Question

Within the confines of a single matrix related method that works with large multidimensional arrays performance and memory usage are critical. We have a need to mutate elements of the array in place and thus are working with ArrayBuffer's (not Array's).

Given this use case is there a way to use for .. yield that would generate an ArrayBuffer (or at the least a mutable collection) instead of immutable?

The following code displays the intent - though it does not compile:

def classify(inarr: Array[Double], arrarr: Array[Array[Double]], labels: Array[String], K: Int): String = {
 ...     
var diffmat: ArrayBuffer[ArrayBuffer[Double]] = for (row <- arrarr) yield {
  (ArrayBuffer[Double]() /: (row zip inarr)) {
    (outrow, cell) => outrow += cell._1 - cell._2
  }
}

The compilation error is :

Expression Array[ArrayBuffer[Double]] does not conform to expected type ArrayBuffer[ArrayBuffer[Double]]
Était-ce utile?

La solution

Ah... a case for the "magick sprinkles" of breakOut. Not only does it give you the collection type you want - it does it efficiently, without wasting an extra transformation.

object Foo {
  import scala.collection.mutable.ArrayBuffer
  import scala.collection.breakOut
  val inarr: Array[Double] = Array()
  val arrarr: Array[Array[Double]] = Array()

  var diffmat: ArrayBuffer[ArrayBuffer[Double]] = (for (row <- arrarr) yield {
    (ArrayBuffer[Double]() /: (row zip inarr)) {
      (outrow, cell) => outrow += cell._1 - cell._2
    }
  })(breakOut)
}

The definitive writeup (IMHO) of this is Daniel Sobral's answer.

Licencié sous: CC-BY-SA avec attribution
Non affilié à StackOverflow
scroll top