Acting on inner and outer loops for multidimensional array in idiomatic scala - scala

I have this nested loop:
for ( y <- 0 to 5) {
for ( x <- 0 to 5) {
print(x, y)
}
println()
}
Is there a cleaner way of expressing this in scala -- bearing in mind I want to do something once for every outer loop iteration, as well as the internal?
The following is the closest I've got:
for {
y <- 0 to 5
x <- 0 to 5
} {
print (x, y) + " "
if(x == 5) println()
}

for {
y <- 0 to 5
x <- 0 to 5
_ = if (x ==5) println()
} print(x, y)
Seems like the most concise way to me.

I don't think for comprehensions are a good option here, why not just use foreach? like this:
(0 to 5).foreach{ y =>
(0 to 5).foreach{ x =>
print (x, y) + " "
}
println()
}

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

Adding elements to a list in a for loop

var locations: List[Location] = List[Location]()
for (x <- 0 to 10; y <- 0 to 10) {
println("x: " + x + " y: " + y)
locations ::: List(Location(x, y))
println(locations)
}
The code above is supposed to concatenate some lists. But the result is an empty list. Why?
Your mistake is on the line locations ::: List(Location(x, y)). This is concatenating the lists, but the doing nothing with the result. If you replace it with locations = locations ::: List(Location(x, y)) you would have your desired result.
However there are more idiomatic ways to solve this problem in Scala. In Scala, writing immutable code is the preferred style (i.e. use val rather than var where possible).
Here's a couple of ways to do it:
Using yield:
val location = for (x <- 0 to 10; y <- 0 to 10) yield Location(x, y)
Using tabulate:
val location = List.tabulate(11, 11) { case (x, y) => Location(x, y) }
Even shorter:
val location = List.tabulate(11, 11)(Location)
Edit: just noticed you had 0 to 10 which is inclusive-inclusive. 0 until 10 is inclusive-exclusive. I've changed the args to tabulate to 11.

scala foreach of a 2-D List/Array in chisel with types issue

Can "foreach" can be used for each element of the 2-D List/Array?
I tried the code:
val n_vec = (0 to 2).map(i=>
(0 to 2).map(j=>
Wire(UInt(3.W))
)
)
n_vec.foreach((i:Int)=>(
n_vec(i).foreach((j:Int)=>{
n_vec(i)(j) := i.U + j.U
})
))
the error message is
top.scala:24: error: type mismatch;
found : Int => Unit
required: chisel3.core.UInt => ?
n_vec(i).foreach((j:Int)=>{
^
Could you enlight me whether it can be used in such a way, even how?
It would be cleaner to write like this:
n_vec.foreach { i=>
i.foreach { j=>
j := x.U + y.U
y = y + 1
}
y = 0
x = x + 1
}
But you don't need to increment x and y manually, just iterate over indices instead:
n_vec.indices.foreach { x =>
n_vec(x).indices.foreach { y =>
n_vec(x)(y) := x.U + y.U
}
}
or better (and this translates exactly to the above)
for {
x <- n_vec.indices
y <- n_vec(x).indices
} {
n_vec(x)(y) := x.U + y.U
}
Yes it can be used this way.
solution:
var x = 0
var y = 0
n_vec.foreach(i=>{
i.foreach(j=>{
j := x.U + y.U
y = y + 1
})
y = 0
x = x + 1
})
x = 0
y = 0

Basic Scala for loop Issue

I am trying to learn scala, here I am using basic for loop, but I am getting errors while compiling.
object App {
def main(args: Array[String]) {
for (i <- 1 to 10; i % 2 == 0)
Console.println("Counting " + i)
}
}
Errors while compiling :
fortest.scala:5: error: '<-' expected but ')' found.
for (i <- 1 to 10; i % 2 == 0)
^
fortest.scala:7: error: illegal start of simple expression
}
^
two errors found
I am using scala version 2.9.1
Any idea what is the problem..............?
for (i <- 1 to 10 if i % 2 == 0)
println("Counting " + i)
Scala is not Java, thus you cannot use a regular Java syntax. Instead you have to do:
for{
i <- 1 to 10
if(i % 2 == 0)
}{println("Counting " + i)}
or with ; delimeters, inside the (,) parentheses:
for(i <- 1 to 10;if(i % 2 == 0)){
println("Counting " + i)
}
Also, note that Scala's for expressions, have some pretty nifty capabilities.
you can use a for expression with multiple "loop iterators" and conditions.
For instance, instead of writing:
for(i <- 1 to n; if(someCondition(i)){
for(j <- 1 to m; if(otherCondition(j)){
//Do something
}
}
You can simply write:
for{
i <- 1 to n
if(someCondition(i))
j <- 1 to m
if(otherCondition(j))
}{
//Do something
}
SIDE NOTE:
When you extend App (there's a trait of that name in Predef), you don't need to define a main method. You can simply write your code between the curly braces of object:
object MyClazz extends App {
for(i <- 1 to 10;if(i % 2 == 0)){
println("Counting " + i)
}
}
Take a look at the "by" method of the Range class to count by 2
object App {
def main(args: Array[String]) {
for (i <- 2 to 10 by 2)
Console.println("Counting " + i)
}
}
Or, like others have already stated you can fix your loop by doing
object App {
def main(args: Array[String]) {
for {
i <- 1 to 10
if i % 2 == 0
}
Console.println("Counting " + i)
}
}
Or another way:
object App {
def main(args: Array[String]) {
val evenNumbers = for {
i <- 1 to 10
if i % 2 == 0
} yield i
Console.println(evenNumbers.mkString("\n"))
}
}
The modulo 2 condition can be moved to an if clause.
object App {
def main(args: Array[String]) {
for (i <- 1 to 10)
if(i % 2 == 0)
Console.println("Counting " + i)
}
}
Here is the simply example;
for (i <- List(1, 2, 3) if i < 2) println(i)
The best way to exam your code is to use scala shell.
Basically, you are trying to use for-loop + iterator gaurd. Please find below syntax
for ( i <- 1 to 10 if (i%2==0) ) yield i

Swapping array values with for and yield scala

I am trying to swap every pair of values in my array using for and yield and so far I am very unsuccessful. What I have tried is as follows:
val a = Array(1,2,3,4,5) //What I want is Array(2,1,4,3,5)
for(i<-0 until (a.length-1,2),r<- Array(i+1,i)) yield r
The above given snippet returns the vector 2,1,4,3(and the 5 is omitted)
Can somebody point out what I am doing wrong here and how to get the correct reversal using for and yields?
Thanks
a.grouped(2).flatMap(_.reverse).toArray
or if you need for/yield (much less concise in this case, and in fact expands to the same code):
(for {b <- a.grouped(2); c <- b.reverse} yield c).toArray
It would be easier if you didin't use for/yield:
a.grouped(2)
.flatMap{
case Array(x,y) => Array(y,x)
case Array(x) => Array(x)
}.toArray // Array(2, 1, 4, 3, 5)
I don't know if the OP is reading Scala for the Impatient, but this was exercise 3.3 .
I like the map solution, but we're not on that chapter yet, so this is my ugly implementation using the required for/yield. You can probably move some yield logic into a guard/definition.
for( i <- 0 until(a.length,2); j <- (i+1).to(i,-1) if(j<a.length) ) yield a(j)
I'm a Java guy, so I've no confirmation of this assertion, but I'm curious what the overhead of the maps/grouping and iterators are. I suspect it all compiles down to the same Java byte code.
Another simple, for-yield solution:
def swapAdjacent(array: ArrayBuffer[Int]) = {
for (i <- 0 until array.length) yield (
if (i % 2 == 0)
if (i == array.length - 1) array(i) else array(i + 1)
else array(i - 1)
)
}
Here is my solution
def swapAdjacent(a: Array[Int]):Array[Int] =
(for(i <- 0 until a.length) yield
if (i%2==0 && (i+1)==a.length) a(i) //last element for odd length
else if (i%2==0) a(i+1)
else a(i-1)
).toArray
https://github.com/BasileDuPlessis/scala-for-the-impatient/blob/master/src/main/scala/com/basile/scala/ch03/Ex03.scala
If you are doing exercises 3.2 and 3.3 in Scala for the Impatient here are both my answers. They are the same with the logic moved around.
/** Excercise 3.2 */
for (i <- 0 until a.length if i % 2 == 1) {val t = a(i); a(i) = a(i-1); a(i-1) = t }
/** Excercise 3.3 */
for (i <- 0 until a.length) yield { if (i % 2 == 1) a(i-1) else if (i+1 <= a.length-1) a(i+1) else a(i) }
for (i <- 0 until arr.length-1 by 2) { val tmp = arr(i); arr(i) = arr(i+1); arr(i+1) = tmp }
I have started to learn Scala recently and all solutions from the book Scala for the Impatient (1st edition) are available at my github:
Chapter 2
https://gist.github.com/carloscaldas/51c01ccad9d86da8d96f1f40f7fecba7
Chapter 3
https://gist.github.com/carloscaldas/3361321306faf82e76c967559b5cea33
I have my solution, but without yield. Maybe someone will found it usefull.
def swap(x: Array[Int]): Array[Int] = {
for (i <- 0 until x.length-1 by 2){
var left = x(i)
x(i) = x(i+1)
x(i+1) = left
}
x
}
Assuming array is not empty, here you go:
val swapResult = for (ind <- arr1.indices) yield {
if (ind % 2 != 0) arr1(ind - 1)
else if (arr1(ind) == arr1.last) arr1(ind)
else if (ind % 2 == 0) arr1(ind + 1)
}