Scala - Most elegant way of initialising values inside array that's already been declared? - scala

I have a 3d array defined like so:
val 3dArray = new Array[Array[Array[Int]]](512, 8, 8)
In Javascript I would do the following to assign each element to 1:
for (i = 0; i < 512; i++)
{
3dArray[i] = [];
for (j = 0; j < 8; j++)
{
3dArray[i][j] = [];
for (k = 0; k < 8; k++)
{
3dArray[i][j][k] = 1;
}
}
}
What's the most elegant approach to doing the same?

Not sure there's a particularly elegant way to do it, but here's one way (I use suffix s to indicate dimension, i.e. xss is a two-dimensional array).
val xsss = Array.ofDim[Int](512, 8, 8)
for (xss <- xsss; xs <- xss; i <- 0 until 8)
xs(i) = 1
Or, using transform it gets even shorter:
for (xss <- xsss; xs <- xss)
xs transform (_ => 1)

for {
i <- a.indices
j <- a(i).indices
k <- a(i)(j).indices
} a(i)(j)(k) = 1
or
for {
e <- a
ee <- e
i <- ee.indices
} ee(i) = 1

See: http://www.scala-lang.org/api/current/index.html#scala.Array$
You have Array.fill to initialize an array of 1 to 5 dimension to some given value, and Array.tabulate to initialize an array of 1 to 5 dimension given the current indexes:
scala> Array.fill(2,1,1)(42)
res1: Array[Array[Array[Int]]] = Array(Array(Array(42)), Array(Array(42)))
enter code here
scala> Array.tabulate(3,2,1){ (x,y,z) => x+y+z }
res2: Array[Array[Array[Int]]] = Array(Array(Array(0), Array(1)), Array(Array(1), Array(2)), Array(Array(2), Array(3)))

Related

For loop with two variables in scala

I have the following java code:
for (int i = 0, j = 0; i < 10 && j < 10 0; i++, j++)
{
System.out.println("i = " + i + " :: " + "j = " + j);
}
The output is :
i = 0 :: j = 0
i = 1 :: j = 1
i = 2 :: j = 2
i = 3 :: j = 3
i = 4 :: j = 4
i = 5 :: j = 5
....
I would like to do the same thing in scala, I tried this but it does not work:
for (i<- 0 to 9; j <- 0 to 9)
{
println("i = " + i + " :: " + "j = " + j)
}
The output is:
i = 0 :: j = 0
i = 0 :: j = 1
i = 0 :: j = 2
i = 0 :: j = 3
i = 0 :: j = 4
i = 0 :: j = 5
i = 0 :: j = 6
i = 0 :: j = 7
i = 0 :: j = 8
i = 0 :: j = 9
i = 1 :: j = 0
i = 1 :: j = 1
i = 1 :: j = 2
i = 1 :: j = 3
....
I have not find a way to have two variables in the same level.
Thank you for your answer.
Scala's replacement would be
for {
(i, j) <- (0 to 9) zip (0 to 9)
} {
println("i = " + i + " :: " + "j = " + j)
}
To avoid the confusion I suggest reading what for is the syntactic sugar for (as opposed to Java it is not specialized while).
Since both variables always have the same value, you actually only need one of them. In Scala, you would generally not use a loop to solve this problem, but use higher-level collection operations instead. Something like:
(0 to 9) map { i => s"i = $i :: j = $i" } mkString "\n"
Note: this will only generate the string that you want to print, but not actually print it. It is generally considered a good thing to not mix generating data and printing data.
If you want to print this, you only need to pass it to println:
println((0 to 9) map { i => s"i = $i :: j = $i" } mkString "\n")
Or, in Scala 2.13+:
import scala.util.chaining._
(0 to 9) map { i => s"i = $i :: j = $i" } mkString "\n" pipe println
You could also write it like this:
(for (i <- 0 to 9) yield s"i = $i :: j = $i") mkString "\n"
Now, you might say, "Wait a minute, didn't you just say that we don't use loops in Scala?" Well, here's the thing: that's not a loop! That is a for comprehension. It is actually syntactic sugar for collection operations.
for (foo <- bar) yield baz(foo)
is actually just syntactic sugar for
bar map { foo => baz(foo) }
A for comprehension simply desugars into calls to map, flatMap, foreach, and withFilter. It is not a loop.
Note that Scala does have a while loop. It exists mainly for performance reasons. Unless you are writing low-level libraries that are going to be used in performance-intensive code by tens of thousands of developers, please just pretend that it doesn't exist.
Also note that if the while loop weren't built into Scala, you could easily write it yourself:
def whiley(cond: => Boolean)(body: => Unit): Unit =
if (cond) { body; whiley(cond)(body) }
you can do it as below
val start = 0; val size = 10;
for ((i, j) <- (start to size) zip (start to size))
{
println(s"i=$i j=$j")
}
j is just a copy of i so this is one solution:
for {
i <- 0 to 9
j = i
} {
println("i = " + i + " :: " + "j = " + j)
}
This pattern works in any situation where j is just a function of i

Getting specific incremental key values into an array

I have a list which I zipped with indices:
val fun_i_map_e = (list.indices zip list).toMap
Now, I want to get each key's value incremented by num:Int :
for (k<-0 until list.length by num)
for ((k,v) <- fun_i_map_e) {
bufferArray += v}
The idea here is something like this in Java:
for (k = 0; k <= list.length; k+= num){
//increment key k each time and store value into dynamic array }
However, I'm getting very random and complete trash output. I would appreciate if someone can help as I'm new in Scala.
You are almost there. All you need is to shape your for function with yield as given below
val bufferArray = for (k <- 0 until list.length by num) yield fun_i_map_e(k)
I hope the answer is helpful
val list = List[Int](5, 6, 7, 8)
val map = list.indices.zip(list).toMap
val num: Int = 15
val incremantedKeys = map.keys.map { k => k + num }
println("Original keys:")
println(map.keys)
println
println(s"Keys incremented by $num:")
println(incremantedKeys)

Best purely functional alternative to a while loop

Is the a better functional idiom alternative to the code below? ie Is there a neater way to get the value j without having to use a var?
var j = i + 1
while (j < idxs.length && idxs(j) == x) j += 1
val j = idxs.drop(i).indexWhere(_ != x) + i
Or, as suggested by #kosii in the comments, use the indexWhere overload that takes an index from where to start searching:
val j = idxs.indexWhere(_ != x, i)
Edit
Since j must equal the length of idxs in case all items following i are equal to x:
val index = idxs.indexWhere(_ != x, i)
val j = if(index < 0) idxs.length else index
// or
val j = if (idxs.drop(i).forall(_ == x)) idxs.length
else idxs.indexWhere(_ != x, i)
Maybe with streams, something like:
((i + 1) to idxs.length).toStream.takeWhile(j => idxs(j) == x).last

Need pointers for optimization of Merge Sort implementation in Scala

I have just started learning Scala and sideways I am doing some algorithms also. Below is an implementation of merge sort in Scala. I know it isn't very "scala" in nature, and some might even reckon that I have tried to write java in scala. I am not totally familiar with scala, i just know some basic syntax and i keep googling if i need something more. So please give me some pointers on to what can i do in this code to make it more functional and in accord with scala conventions and best practices. Please dont just give correct/optimized code, i will like to do it myself. Any suggestions are welcomed !
def mergeSort(list: Array[Int]): Array[Int] = {
val len = list.length
if (len == 1) list
else {
var x, y = new Array[Int](len / 2)
val z = new Array[Int](len)
Array.copy(list, 0, x, 0, len / 2)
Array.copy(list, len / 2, y, 0, len / 2)
x = mergeSort(x)
y = mergeSort(y)
var i, j = 0
for (k <- 0 until len) {
if (j >= y.length || (i < x.length && x(i) < y(j))) {
z(k) = x(i)
i = i + 1
} else {
z(k) = y(j)
j = j + 1
}
}
z
}
}
[EDIT]
This code works fine and I have assumed for now that input array will always be of even length.
UPDATE
Removed vars x and y
def mergeSort(list: Array[Int]): Array[Int] = {
val len = list.length
if (len == 1) list
else {
val z = new Array[Int](len)
val x = mergeSort(list.dropRight(len/2))
val y = mergeSort(list.drop(len/2))
var i, j = 0
for (k <- 0 until len) {
if (j >= y.length || (i < x.length && x(i) < y(j))) {
z(k) = x(i)
i = i + 1
} else {
z(k) = y(j)
j = j + 1
}
}
z
}
}
Removing the var x,y = ... would be a good start to being functional. Prefer immutability to mutable datasets.
HINT: a method swap that takes two values and returns them ordered using a predicate
Also consider removing the for loop(or comprehension).

Scala best practices: mapping 2D data

What would be the best way in Scala to do the following code in Java in proper functional way?
LinkedList<Item> itemsInRange = new LinkedList<Item>();
for (int y = 0; y < height(); y++) {
for (int x = 0; x < width(); x++) {
Item it = myMap.getItemAt(cy + y, cx + x);
if (it != null)
itemsInRange.add(it);
}
}
// iterate over itemsInRange later
Over course, it can be translated directly into Scala in imperative way:
val itemsInRange = new ListBuffer[Item]
for (y <- 0 until height) {
for (x <- 0 until width) {
val it = tileMap.getItemAt(cy + x, cx + x)
if (!it.isEmpty)
itemsInRange.append(it.get)
}
}
But I'd like to do it in proper, functional way.
I presume that there should be map operation over some sort of 2D range. Ideally, map would execute a function that would get x and y as input parameters and output Option[Item]. After that I'll get something like Iterable[Option[Item]] and flatten over it will yield Iterable[Item]. If I'm right, the only missing piece of a puzzle is doing that map operation on 2D ranges in some way.
You can do this all in one nice step:
def items[A](w: Int, h: Int)(at: ((Int, Int)) => Option[A]): IndexedSeq[A] =
for {
x <- 0 until w
y <- 0 until h
i <- at(x, y)
} yield i
Now say for example we have this representation of symbols on a four-by-four board:
val tileMap = Map(
(0, 0) -> 'a,
(1, 0) -> 'b,
(3, 2) -> 'c
)
We just write:
scala> items(4, 4)(tileMap.get)
res0: IndexedSeq[Symbol] = Vector('a, 'b, 'c)
Which I think is what you want.