Getting specific incremental key values into an array - scala

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)

Related

Scala for loop to calculate sum of powers

I am very new to Scala and am trying to create a loop that will calculate the sum of powers (1^1 + 2^2 + ... + 10^10) without using an exponent operator.
I discovered that 1^1 through 9^9 calculate correctly. But for some reason 10^10 evaluates to 1410065409 in my current code and messes up my final output of the sum. What is causing this mathematical error?
My current code is:
var i = 1
var ex = 1
var sum = 0
while (i <= 10)
{
for (j <- 1 to i)
{
ex = ex * i
}
sum += ex
ex = 1
i += 1
}
println(s"The sum is $sum")
Here's how it's done in Scala.
List.tabulate(10)(n => List.fill(n+1)(n.toLong+1).product).sum
//res0: Long = 10405071317
Another option you have, is to use Math.pow:
val result1 = 1.to(10).map(x => Math.pow(x, x)).sum
Please note that result1 is of type Double, and has the value 1.0405071317E10.
If you want to have it as long, you can do:
val result2 = 1.to(10).map(x => Math.pow(x, x).toLong).sum
Then result2 will have the value 10405071317.

List whose elements depend on the previous ones

Suppose I have a list of increasing integers. If the difference of 2 consecutive numbers is less than a threshold, then we index them by the same number, starting from 0. Otherwise, we increase the index by 1.
For example: for the list (1,2,5,7,8,11,15,16,20) and the threshold = 3, the output will be: (0, 0, 1, 1, 1, 2, 3, 3, 4).
Here is my code:
val listToGroup = List(1,2,5,7,8,11,15,16,20)
val diff_list = listToGroup.sliding(2,1).map{case List(i, j) => j-i}.toList
val thres = 2
var j=0
val output_ = for(i <- diff_list.indices) yield {
if (diff_list(i) > thres ) {
j += 1
}
j
}
val output = List.concat(List(0), output_)
I'm new to Scala and I feel the list is not used efficiently. How can this code be improved?
You can avoid the mutable variable by using scanLeft to get a more idiomatic code:
val output = diff_list.scanLeft(0) { (count, i) =>
if (i > thres) count + 1
else count
}
Your code shows some constructs which are usually avoided in Scala, but common when coming from procedural langugues, like: for(i <- diff_list.indices) ... diff_list(i) can be replaced with for(i <- diff_list).
Other than that, I think your code is efficient - you need to traverse the list anyway and you do it in O(N). I would not worry about efficiency here, more about style and readability.
My rewrite to how I think it would be more natural in Scala for the whole code would be:
val listToGroup = List(1,2,5,7,8,11,15,16,20)
val thres = 2
val output = listToGroup.zip(listToGroup.drop(1)).scanLeft(0) { case (count, (i, j)) =>
if (j - i > thres) count + 1
else count
}
My adjustments to your code:
I use scanLeft to perform the result collection construction
I prefer x.zip(x.drop(1)) over x.sliding(2, 1) (constructing tuples seems a bit more efficient than constructing collections). You could also use x.zip(x.tail), but that does not handle empty x
I avoid the temporary result diff_list
val listToGroup = List(1, 2, 5, 7, 8, 11, 15, 16, 20)
val thres = 2
listToGroup
.sliding(2)
.scanLeft(0)((a, b) => { if (b.tail.head - b.head > thres) a + 1 else a })
.toList
.tail
You don't need to use mutable variable, you can achieve the same with scanLeft.

How do I append an element to a list in Scala

I have a list:
val k = List(1,2,3,4,-69,78)
and would like to remove all negative elements in the list
I have the following code:
val k = List(1,2,3,4,-69,78)
val a = List()
for( k <- k){
if(k > 0){
a=a:+k
}
}
println(a)
What it is supposed to run through the list and if an element in the list is positive, it should append it to another list in this case list a
however I get the following error:
ScalaFiddle.scala:9: error: reassignment to val
a=a:+k
^
how can I fix this
Please note that I intentionally do not want to use l.filter.
If anyone has a better Idea as to how I can do this, it would be greatly appreciated
Thanks in advance
You are doing in a Java way.
In Scala you should avoid mutable variables and use immutable variables as much as possible.
A better "Scala" solution for your problem is to do the following:
val k = List(1,2,3,4,-69,78)
val a = k.filter(_ > 0)
If you still want to append to the list, you need to change a to be:
val a = new mutable.MutableList[Int]()
And append like this:
a += k
You are trying to reassign a value to a constant (i.e val) which is not possible, the List a needs to be var instead:
val k = List(1,2,3,4,-69,78)
var a = List[Int]()
for(k <- k){
if(k > 0){
a = a :+ k
}
}
println(a)
// Display List(1, 2, 3, 4, 78)
You should use val instead of var.
In short: var can be modified after initialized and val not.
But is important to notice that Scala discourage the use of var because of immutability.
val k = List(1,2,3,4,-69,78)
var a: List[Int] = List()
for( k <- k){
if(k > 0){
a=a:+k
}
}
println(a)
val in scala cannot be reassigned.
When you write val a = List(), you are getting a which holds empty list.
When you write a :+ k you get new list, and you have to assign it to another value in order to access it in future, problem is that you cant reassign a cause it is val.
You could use var but this way is considered as a bad practice.
Another solution is to use functions:
def onlyPositives(k: List[Int], a: List[Int] = List.empty[Int]): List[Int] = k match {
// case when there is no elements left in k
case Nil => a
// we get first element of k and
// if it is positive, append it to a
case x::tail => onlyPositives(tail, if (x > 0) a:+x else a)
}
Now you can write:
val k = List(1, 2, 3, 4, -69, 78)
val a = onlyPositives(k) // List(1, 2, 3, 4, 78)
P. S.
I wonder why you do not use the filter?

How to print a value outside a for loop in scala?

I am new to scala and would like to know way to access val which is defined inside for loop and would like to write that val to a file outside for loop.
def time[A](logFile: String, description: String)(job: => A): Unit = {
var totalDuration: Long = 0
for (i <- 1 to 3) {
val currentTime = System.currentTimeMillis
val result = job
val finalTime = System.currentTimeMillis
val duration = finalTime - currentTime
totalDuration = if (totalDuration == 0) duration else totalDuration.min(duration)
}
val pw = new PrintWriter(new FileOutputStream(new File(logFile),true))
pw.write(description + " " + result + " " + totalDuration +" ms"+"\n")
pw.flush()
pw.close
}
In the above code i am calculating my result which contains the length of bytes read from other function and would like to calculate the time it takes to read the total bytes. I would like to iterate 3 times and take the minimum of all the three. The val result contains the bytes length which also needs to be written in a file. i get a error because i am accessing the result val outside the scope of for loop. Can someone please help me solve this error. How can i access the val result outside for loop to write it to a file ?
Thanks in advance!!
While your question is answered, the for loop is not in it's typical form, which would look more like this:
def time[A] (logFile: String, description: String) (job: => A): Unit = {
val (result, totalDuration): (A, Long) = (for { i <- 1 to 3
currentTime = System.currentTimeMillis
result = job
finalTime = System.currentTimeMillis
duration = finalTime - currentTime
} yield (result, duration)).minBy {case (r, d) => d}
val pw = new PrintWriter (new FileOutputStream (new File (logFile), true))
pw.write (description + " " + result + " " + totalDuration +" ms"+"\n")
pw.flush()
pw.close
}
If I understood your code correctly. I don't know whether a side effect yields to different results for each job invocation.
I missed the internal discussion of the for-loop invention/definition, why the keyword val should be omitted here, but it is quiet handy.
What is more important, is, that you usually have all temporary assignments in the for (...(here part)...) { not here}. The consequences of round or curly braces in the first part aren't totally clear to me, but if you use round parens, you have terminate most statements with a semicolon.
scala> for (i <- 1 to 3;
| j <- 4 to 5;
| k = j-i;
| l = k/2) yield l * l;
res2: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 0, 1)
Note that neither i, nor j, k, l where declared as val or var.
scala> for {i <- 1 to 3
| j <- 4 to 5
| k = j-i
| l = k/2} yield l * l;
res3: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 0, 1)
You will find multiple questions here, which explain, how a for-loop is and can be translatet to a flatMap/map-combination, eventually with filter:
scala> for {i <- 1 to 3
| j <- 4 to 5
| k = j-i
| if (k > 1)
| l = k/2 } yield l * l;
res5: scala.collection.immutable.IndexedSeq[Int] = Vector(1, 4, 1, 1, 1)
And instead of yielding just one value, you can yield a tuple, and assign by
val (a:X, b:Y) = (for ..... yield (aa, bb))
The
yield (result, duration)).minBy {case (r, d) => d}
takes a tuple (result, duration) and selects the minimum by duration, but yields both values.
you can use yield. Yield will return data from for loop after completion of loop and use that data accordingly. Since I do not have your code. see this example
val j = for (i <- 1 to 10) yield i
println(j)
output of j will be
Vector(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)
For replacing your for loop to calculate the total duration of some jobs that are executed sequentially, you could use foldLeft
Make use of yield or you can use any of the fold method. Or if you are good with recursion you can use a tailrec method which returns what is Desired. Yield is the most simplest way to do it.
val answer = for(i<- 1 to 10) yield i
println(answer) // Vector(1,2,3,4,5,6,7,8,9,10)

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

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)))