How do I create an array of multiple dimensions?
For example, I want an integer or double matrix, something like double[][] in Java.
I know for a fact that arrays changed in Scala 2.8 and that the old arrays are deprecated, but are there multiple ways to do it now and if yes, which is best?
Like so:
scala> Array.ofDim[Double](2, 2, 2)
res2: Array[Array[Array[Double]]] = Array(Array(Array(0.0, 0.0), Array(0.0, 0.0)), Array(Array(0.0, 0.0), Array(0.0, 0.0)))
scala> {val (x, y) = (2, 3); Array.tabulate(x, y)( (x, y) => x + y )}
res3: Array[Array[Int]] = Array(Array(0, 1, 2), Array(1, 2, 3))
It's deprecated. Companion object exports factory methods ofDim:
val cube = Array.ofDim[Float](8, 8, 8)
How to create and use a multi-dimensional array in Scala?
var dd : Array[(Int, (Double, Double))] = Array((1,(0.0,0.0)))
Related
I'm trying to define a type for a matrix (two dimensional array). I have this:
scala> type DMatrix[T] = Array[Array[T]]
defined type alias DMatrix
and then I define de DMatrix:
scala> def DMatrix = Array.ofDim[Double](2,2)
DMatrix: Array[Array[Double]]
So far so good. The problem now is how to work with th DMatrix. I've tried some examples but nothing happens:
scala> DMatrix(0)(0) = 1.0
scala> DMatrix
res40: Array[Array[Double]] = Array(Array(0.0, 0.0), Array(0.0, 0.0))
scala> DMatrix(0)
res41: Array[Double] = Array(0.0, 0.0)
scala> DMatrix(0) = Array(1.0,2.1)
scala> DMatrix(0)
res43: Array[Double] = Array(0.0, 0.0)
so, the question is how to use this DMatrix type?
thanks in advance
There's just a tiny but crucial mistake here - in:
scala> def DMatrix = Array.ofDim[Double](2,2)
You've used def instead of val to declare DMatrix: that means that the expression is evaluated anew everytime you access it, so when you modify the values in the arrays, the result is "thrown away" in favor of a new DMatrix instance.
Changing it to val would fix the issue and you'll see all changes:
scala> val DMatrix = Array.ofDim[Double](2,2)
DMatrix: Array[Array[Double]] = Array(Array(0.0, 0.0), Array(0.0, 0.0))
scala> DMatrix(0)(0) = 1.0
scala> DMatrix
res1: Array[Array[Double]] = Array(Array(1.0, 0.0), Array(0.0, 0.0))
If I have an array of array (similar to a matrix) in Scala, what's the efficient way to sum up each column of the matrix? For example, if my array of array is like below:
val arr = Array(Array(1, 100, ...), Array(2, 200, ...), Array(3, 300, ...))
and I want to sum up each column (e.g., sum up the first element of all sub-arrays, sum up the second element of all sub-arrays, etc.) and get a new array like below:
newArr = Array(6, 600, ...)
How can I do this efficiently in Spark Scala?
There is a suitable .transpose method on List that can help here, although I can't say what its efficiency is like:
arr.toList.transpose.map(_.sum)
(then call .toArray if you specifically need the result as an array).
Using breeze Vector:
scala> val arr = Array(Array(1, 100), Array(2, 200), Array(3, 300))
arr: Array[Array[Int]] = Array(Array(1, 100), Array(2, 200), Array(3, 300))
scala> arr.map(breeze.linalg.Vector(_)).reduce(_ + _)
res0: breeze.linalg.Vector[Int] = DenseVector(6, 600)
If your input is sparse you may consider using breeze.linalg.SparseVector.
In practice a linear algebra vector library as mentioned by #zero323 will often be the better choice.
If you can't use a vector library, I suggest writing a function col2sum that can sum two columns -- even if they are not the same length -- and then use Array.reduce to extend this operation to N columns. Using reduce is valid because we know that sums are not dependent on order of operations (i.e. 1+2+3 == 3+2+1 == 3+1+2 == 6) :
def col2sum(x:Array[Int],y:Array[Int]):Array[Int] = {
x.zipAll(y,0,0).map(pair=>pair._1+pair._2)
}
def colsum(a:Array[Array[Int]]):Array[Int] = {
a.reduce(col2sum)
}
val z = Array(Array(1, 2, 3, 4, 5), Array(2, 4, 6, 8, 10), Array(1, 9));
colsum(z)
--> Array[Int] = Array(4, 15, 9, 12, 15)
scala> val arr = Array(Array(1, 100), Array(2, 200), Array(3, 300 ))
arr: Array[Array[Int]] = Array(Array(1, 100), Array(2, 200), Array(3, 300))
scala> arr.flatten.zipWithIndex.groupBy(c => (c._2 + 1) % 2)
.map(a => a._1 -> a._2.foldLeft(0)((sum, i) => sum + i._1))
res40: scala.collection.immutable.Map[Int,Int] = Map(2 -> 600, 1 -> 6, 0 -> 15)
flatten array and zipWithIndex to get index and groupBy to map new array as column array, foldLeft to sum the column array.
I create zeroed Arrays in Scala with
(0 until Nrows).map (_ => 0).toArray but is there anything faster ? map is slow.
I have the same question but with 1 instead of O, i.e. I also want to accelerate (0 until Nrows).map (_ => 1).toArray
Zero is the default value for an array of Ints, so just do this:
val array = new Array[Int](NRows)
If you want all those values to be 1s then use .fill() (with thanks to #gourlaysama):
val array = Array.fill(NRows)(1)
However, looking at how this works internally, it involves the creation of a few objects that you don't need. I suspect the following (uglier) approach may be quicker if speed is your main concern:
val array = new Array[Int](NRows)
for (i <- 0 until array.length) { array(i) = 1 }
For multidimensional arrays consider Array.ofDim, for instance,
scala> val a = Array.ofDim[Int](3,3)
a: Array[Array[Int]] = Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0))
Likewise,
scala> val a = Array.ofDim[Int](3)
a: Array[Int] = Array(0, 0, 0)
In the context here,
val a = Array.ofDim[Int](NRows)
For setting (possibly nonzero) initial values, consider Array.tabulate, for instance,
scala> Array.tabulate(3,3)( (x,y) => 1)
res5: Array[Array[Int]] = Array(Array(1, 1, 1), Array(1, 1, 1), Array(1, 1, 1))
scala> Array.tabulate(3)( x => 1)
res18: Array[Int] = Array(1, 1, 1)
What's the recommended way of creating a pre-populated two-dimensional array in Scala? I've got the following code:
val map = for {
x <- (1 to size).toList
} yield for {
y <- (1 to size).toList
} yield (x, y)
How do I make an array instead of list? Replacing .toList with .toArray doesn't compile. And is there a more concise or readable way of doing this than the nested for expressions?
On Scala 2.7, use Array.range:
for {
x <- Array.range(1, 3)
} yield for {
y <- Array.range(1, 3)
} yield (x, y)
On Scala 2.8, use Array.tabulate:
Array.tabulate(3,3)((x, y) => (x, y))
Among other ways, you can use use Array.range and map:
scala> Array.range(0,3).map(i => Array.range(0,3).map(j => (i,j)))
res0: Array[Array[(Int, Int)]] = Array(Array((0,0), (0,1), (0,2)), Array((1,0), (1,1), (1,2)), Array((2,0), (2,1), (2,2)))
Or you can use Array.fromFunction:
scala> Array.fromFunction((i,j) => (i,j))(3,3)
res1: Array[Array[(Int, Int)]] = Array(Array((0,0), (0,1), (0,2)), Array((1,0), (1,1), (1,2)), Array((2,0), (2,1), (2,2)))
Scala 2.8 gives you even more options--look through the Array object. (Actually, that's good advice for 2.7, also....)
How do I create an array of multiple dimensions?
For example, I want an integer or double matrix, something like double[][] in Java.
I know for a fact that arrays changed in Scala 2.8 and that the old arrays are deprecated, but are there multiple ways to do it now and if yes, which is best?
Like so:
scala> Array.ofDim[Double](2, 2, 2)
res2: Array[Array[Array[Double]]] = Array(Array(Array(0.0, 0.0), Array(0.0, 0.0)), Array(Array(0.0, 0.0), Array(0.0, 0.0)))
scala> {val (x, y) = (2, 3); Array.tabulate(x, y)( (x, y) => x + y )}
res3: Array[Array[Int]] = Array(Array(0, 1, 2), Array(1, 2, 3))
It's deprecated. Companion object exports factory methods ofDim:
val cube = Array.ofDim[Float](8, 8, 8)
How to create and use a multi-dimensional array in Scala?
var dd : Array[(Int, (Double, Double))] = Array((1,(0.0,0.0)))