Scala: iteration 2d array to do operation - arrays

A newbie here.
val arr_one = Array(Array(1, 2), Array(3, 4), Array(5, 6),Array(x, y)..and so on)
val arr_two = Array(Array(2,3), Array(4, 5), Array(6, 7))
var tempArr = ArrayBuffer[Double]()
I want to multiply arr_one and arr_two. for example
Iteration1 :Array(1*2+2*3, 1*4 +2*5, 1*6+2*7 ) assign to tempArr
Iteration2 :Array(3*2+4*3, 3*4 +4*5, 3*6+4*7) assign to tempArr
Iteration3 :Array(5*2+6*3, 5*4 +6*5, 5*6+6*7) assign to tempArr
I knew that if
val x = Array(1, 2) ; val y = Array(Array(2,3), Array(4, 5), Array(6, 7))
I can use y map {x zip _ map{case(a, b) => a * b} sum}
But If x like arr_one form, I don't know how to use for loop or something else to do that.
I really have on idea.
How can I do this in scala?
Really thanks.

I believe this does what you need, without any mutable state and "iterations" - it uses the "for-comprehension" syntax which is kind of a non-imperative for-loop - in other words, instead of changing state in each iteration, it returns a value which is the sequence of results per "iteration":
val result: Array[Array[Int]] = for (arr1 <- arr_one) yield {
for (arr2 <- arr_two) yield multArrays(arr1, arr2)
}
Assuming that multArrays has the following signature:
def multArrays(arr1: Array[Int], arr2: Array[Int]): Int
That calculates the value for each cell. A naive implementation (assuming arrays have size 2) would be:
def multArrays(arr1: Array[Int], arr2: Array[Int]): Int = {
arr1(0) * arr2(0) + arr1(1) * arr2(1)
}
But of course this can be generalized to any size arrays.

May be this is what you need:
val tmp = arr_one map ((arr1) => {arr_two map (arr2 => (arr1 zip arr2) map {case(a, b) => a * b} reduce (_ + _))} )
And to get ArrayBuffer simply use :
tmpArr = tmp.toBuffer

Related

Convert IndexedSeq to Array

I have a 2D Array, say a 3x3 Matrix, and want to multiply all elements with a given value. This is what I have so far:
val m = Array(
Array(1,2,3),
Array(4,5,6),
Array(7,8,9)
)
val value = 3
for ( i <- m.indices) yield m(i).map(x => x*value)
//Result:
//IndexedSeq[Array[Int]] = Vector(Array(3, 6, 9), Array(12, 15, 18), Array(21, 24, 27))
Problem is I have an IndexedSeq[Array[Int]] now but I need this to be an Array[Array[Int]] just like val m.
I know that for example for (i <- Array(1, 2, 3)) yield i results in an Array[Int] but I can't figure out how to put this all together.
Just appending .toArray doesn't work also
If you want to create new Array instances (copy):
val m = Array(
Array(1,2,3),
Array(4,5,6),
Array(7,8,9)
)
val value = 3
val newM = m.map{ array => array.map{x => x * value}}
Or, if you want to modify the original arrays "in-place":
val m = Array(
Array(1,2,3),
Array(4,5,6),
Array(7,8,9)
)
val value = 3
for (arr <- m; j <- arr.indices) {
arr(j) *= value
}

How do I take slice from an array position to end of the array?

How do I get an array of array with elements like this? Is there an inbuilt scala api that can provide this value (without using combinations)?
e.g
val inp = Array(1,2,3,4)
Output
Vector(
Vector((1,2), (1,3), (1,4)),
Vector((2,3), (2,4)),
Vector((3,4))
)
My answer is below. I feel that there should be an elegant answer than this in scala.
val inp = Array(1,2,3,4)
val mp = (0 until inp.length - 1).map( x => {
(x + 1 until inp.length).map( y => {
(inp(x),inp(y))
})
})
print(mp)
+Edit
Added combination constraint.
Using combinations(2) and groupBy() on the first element (0) of each combination will give you the values and structure you want. Getting the result as a Vector[Vector]] will require some conversion using toVector
scala> inp.combinations(2).toList.groupBy(a => a(0)).values
res11: Iterable[List[Array[Int]]] = MapLike.DefaultValuesIterable
(
List(Array(2, 3), Array(2, 4)),
List(Array(1, 2), Array(1, 3), Array(1, 4)),
List(Array(3, 4))
)
ORIGINAL ANSWER
Note This answer is OK only if the elements in the Seq are unique and sorted (according to <). See edit for the more general case.
With
val v = a.toVector
and by foregoing combinations, I can choose tuples instead and not have to cast at the end
for (i <- v.init) yield { for (j <- v if i < j) yield (i, j) }
or
v.init.map(i => v.filter(i < _).map((i, _)))
Not sure if there's a performance hit for using init on vector
EDIT
For non-unique elements, we can use the indices
val v = a.toVector.zipWithIndex
for ((i, idx) <- v.init) yield { for ((j, jdx) <- v if idx < jdx) yield (i, j) }

Faster way to make a zeroed array in Scala

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)

Compare size of 2 Arrays in Scala

If I have 2 arrays, how do I compare them and return the size of the smallest one? Here is what I mean:
val a = Array(1,2,3)
val b = Array(1,2,3,4)
is there some operator that I could call to compare the sizes of both and return 3, since Array a is smaller and has 3 elements?
scala> val a = Array(1,2,3)
a: Array[Int] = Array(1, 2, 3)
scala> val b = Array(1,2,3,4)
b: Array[Int] = Array(1, 2, 3, 4)
scala> math.min(a.length, b.length)
res0: Int = 3
A more generic approach, assuming you want to compare Sequences of the same type.
def getSmallerCollectionSize[T](a:Seq[T],b:Seq[T]) =
Math.min(a.size, b.size)
scala> val a = Array(1,2,3)
a:Array[Int] = Array(1,2,3)
scala> val b = Array(1,2,3,4)
b:Array[Int] = Array(1,2,3,4)
scala> a.size min b.size
res0: Int = 3
The size method gets the size of the Array and min is a comparator function between the two sizes. As with any function taking two parameters, you can call it by putting the function name between the parameters.
min is doing an implicit conversion (a set of methods that Scala tries to apply when it encounters an object of the wrong type being used) from Int to RichInt.

Scala logical indexing with for comprehension

I'm trying to translate the following Matlab logical-indexing pattern into Scala code:
% x is an [Nx1] array of Int32
% y is an [Nx1] array of Int32
% myExpensiveFunction() processes batches of unique x.
ux = unique(x);
z = nan(size(x));
for i = 1:length(ux)
idx = x == ux(i);
z(idx) = myExpensiveFuntion(x(idx), y(idx));
end
Assume I'm working with val x: Array[Int] in Scala. What is the best way to do this?
Edit: To clarify, I'm looking to process batches of (x,y) at a time, grouped by unique x, and return a result (z) with an order corresponding to the initial input. I'm open to sorting x, but eventually need to get back to the original unsorted order. My primary requirement is to handle all the indexing/mapping/sorting in a clear and reasonably efficient way.
Most of this is pretty straightforward in Scala; the only thing that's a bit out of the ordinary is the unique x indices. In Scala you'd do that with a `groupBy'. Since this is a really index-heavy method, I'm just going to give in and go with indices all the way:
val z = Array.fill(x.length)(Double.NaN)
x.indices.groupBy(i => x(i)).foreach{ case (xi, is) =>
is.foreach(i => z(i) = myExpensiveFunction(xi, y(i)))
}
z
assuming you can live with a lack of vectors going to myExpensiveFunction. If not,
val z = Array.fill(x.length)(Double.NaN)
x.indices.groupBy(i => x(i)).foreach{ case (xi, is) =>
val xs = Array.fill(is.length)(xi)
val ys = is.map(i => y(i)).toArray
val zs = myExpensiveFunction(xs, ys)
is.foreach(i => z(i) = zs(i))
}
z
This isn't the most natural way to do the computation in Scala, or the most efficient, but you don't care about efficiency if your expensive function is expensive, and it's the closest I can come to a literal translation.
(Translating your matlab-algorithms into almost everything else involves a certain amount of pain or rethinking, since the "natural" computations in matlab are not like those in most other languages.)
The important point is to get Matlab's unique right. A simple solution would be to use a Set to determine the unique values:
val occurringValues = x.toSet
occurringValues.foreach{ value =>
val indices = x.indices.filter(i => x(i) == value)
for (i <- indices) {
z(i) = myExpensiveFunction(x(i), y(i))
}
}
Note: I assume that it is possible to change myExpensiveFunction to element-wise operation...
scala> def process(xs: Array[Int], ys: Array[Int], f: (Seq[Int], Seq[Int]) => Double): Array[Double] = {
| val ux = xs.distinct
| val zs = Array.fill(xs.size)(Double.NaN)
| for(x <- ux) {
| val idx = xs.indices.filter{ i => xs(i) == x }
| val res = f(idx.map(xs), idx.map(ys))
| idx foreach { i => zs(i) = res }
| }
| zs
| }
process: (xs: Array[Int], ys: Array[Int], f: (Seq[Int], Seq[Int]) => Double)Array[Double]
scala> val xs = Array(1,2,1,2,3)
xs: Array[Int] = Array(1, 2, 1, 2, 3)
scala> val ys = Array(1,2,3,4,5)
ys: Array[Int] = Array(1, 2, 3, 4, 5)
scala> val f = (a: Seq[Int], b: Seq[Int]) => a.sum/b.sum.toDouble
f: (Seq[Int], Seq[Int]) => Double = <function2>
scala> process(xs, ys, f)
res0: Array[Double] = Array(0.5, 0.6666666666666666, 0.5, 0.6666666666666666, 0.6)

Resources