I tried below code but it ultimately prints 5 zeros after giving the user defined values to array .
the below code takes array of size 5 and gives user defined values
object printarray {
def main(args:Array[String]) {
val arr = new Array[Int](5)
println("the values of array is ")
for(i<-0 to 4) {
val arr = scala.io.StdIn.readInt()
}
arr.foreach(println)
}
}
There are a couple of things that need improvement in the code.
You allocate an array of 5 elements named arr in the scope of the main method, but you also declare an additional value with the same name, arr, inside the for comprehension scope and read an Int into it, which you discard once you exit the for scope. Then, you print the array in the outer scope, which hasn't changed at all.
The first thing you need to make this work, is index into the array instead of creating a new value named arr in the inner scope:
object printarray {
def main(args:Array[String]) {
val arr = new Array[Int](5)
println("the values of array is ")
for (i <- 0 to 4) {
arr(i) = scala.io.StdIn.readInt()
}
arr.foreach(println)
}
}
To improve things further, you use the yield Scala synax to make this more concise:
val arr = for (i <- 0 to 4) yield StdIn.readInt()
This will not return an Array[Int], but an IndexedSeq[Int] with an underlying type of Vector[Int]. If you still want an Array[Int], you'll have to explicitly call toArray:
val arr: Array[Int] = (for (i <- 0 to 4) yield scala.io.StdIn.readInt()).toArray
In your for-loop you are reassigning the variable in every iteration. You can change it to:
for(i <- 0 to 4) {
arr(i) = scala.io.StdIn.readInt()
}
As a side-note, instead of declaring the arr before the loop you can simply do:
val arr = for(i <- 0 to 4) yield scala.io.StdIn.readInt()
Related
I want to add one to the array values that are next to the current iteration.
Although at the end result is right, if we see the print(item) result, it still prints the old values.
var arr3 = [1,2,3]
for (index,item) in arr3.enumerated() {
if index+1 == arr3.count {
// Do nothing
} else {
arr3[index + 1] = arr3[index+1] + 1
}
print(item)
}
print(arr3)
Result :
1
2
3
[1,3,4]
Expected :
1
3
4
[1,3,4]
How is this possible?
You might expect the loop using enumerated() to behave the same as looping over the indices and having let item = arr3[index]:
for index in arr3.indices {
let item = arr3[index]
print(item)
if index+1 != arr3.count {
arr3[index + 1] += 1
}
}
However, this is not true. enumerated() produces an EnumeratedSequence<[Int]>. (See the source code for EnumeratedSequence and enumerated()). To create an EnumeratedSequence, the original array arr3 is passed to its initialiser:
public func enumerated() -> EnumeratedSequence<Self> {
return EnumeratedSequence(_base: self)
}
As you may know, Array is a (copy-on-write) value type. When you modify arr3 in the loop, a modified copy is created and assigned to arr3, and the array that the EnumeratedSequence has (i.e. the array over which the loop is iterating), is unaffected. enumerated() is sort of creating a "snapshot" of the array at the time when you called it, so all the print(item) will only print the old items.
There is something wrong with the compiler or my understanding of Go. I have a weird bug and have whittled it down to a simple example. For some reason I can't change the array directly within a loop.
var nums [2]int
for i, v := range nums {
if i == 0 {
nums[i+1]++
} else {
fmt.Print(v)
}
}
This increments nums[1] then prints it. So it should print 1 but it prints 0.
When you use an array in an expression you get its "value" (ie, a complete new copy of the array). This includes using an array in the range expression of a loop. So when you print v you are printing the copy, but the actual nums array has been changed.
Looping on a slice instead of the array gives you what you expect:
var nums [2]int
for i, v := range nums[:] {
if i == 0 {
nums[i+1]++
} else {
fmt.Print(v)
}
}
The range creates a copy of the array (and its values), so it can iterate over them.
If you plan on mutating an array (or a slice of that matter) during iteration, it's best to reference the array/slice directly - as the v value will be a copy and in your code an old copy of the array.
So try something like:
var nums [2]int
for i := range nums {
if i == 0 {
nums[i+1]++
} else {
fmt.Print(nums[i])
}
}
Playground
I'm trying to build a algorithm that can find duplicates in an array, without Using any pre-implemented functions such as "sort" etc.
I have no error but my function does not work… Do you have any idea why? (I'm just starting Scala programming)
def duplicate(s: Array[Int], length: Int): Boolean = {
var i = 0 // start counting at value 0
var j = 0
var result:Boolean = false
var isDupli:Boolean = false
while(j < length && result == false) {
if (s(i) == s(j)) {
isDupli = true
result = true
}
j += 1
}
result
}
var myArray = Array(2,2,2,2)
duplicate(Array(2,2), 2)
I found some code online but people are Using the function sort. My goal is to scroll through the array to find for any duplicates...
Some observations on your code:
You only look at the first (0th) element, and never increment i, so you don't check any of the subsequent elements for duplication.
The length argument is redundant, since we can discover the length of the Array, s, via its .length (or .size) attribute. Using the .length attribute is safer, because it is always valid. For example, duplicate(Array(1, 2, 3, 4, 5, 3), 10) causes an exception (java.lang.ArrayIndexOutOfBoundsException) since the array doesn't have 10 members.
You initialize j to have the same value as i, and then compare s(i) == s(j), so you're always going to get a duplicate on the first element, even if there's no duplication in the array.
You return result (which indicates whether you've found a result), rather than isDupli (which indicates whether you found a duplicate). Fortunately, we only need one of these, since finding a result is the same as finding a duplicate.
Here's another version that fixes these problems, and simplifies some code:
def duplicate(s: Array[Int]): Boolean = {
val length = s.length
var i = 0 // start counting at value 0
var foundDuplicate = false // Type inference means Scala knows this is Boolean
// Loop through each member until we've found a duplicate.
//
// Note that "!foundDuplicate" is the same as "foundDuplicate == false"
while(i < length && !foundDuplicate) {
// Now compare to each of the remaining elements. Start at the element above i.
var j = i + 1
// Loop through each of the remaining elements.
while(j < length && !foundDuplicate) {
// If we find a match, we're done.
if (s(i) == s(j)) {
foundDuplicate = true
}
// Look at the next j
j += 1
}
// Look at the next i
i += 1
}
// Return the result. If we didn't find anything, this will still be false.
foundDuplicate
}
val myArray1 = Array(1, 2, 3, 4, 5, 6, 2, 8, 9)
val myArray2 = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
duplicate(myArray1) // Returns true
duplicate(myArray2) // Returns false
However, while this is perfectly OK procedural code, in Scala we can use a much better functional style. (Procedural code uses vars, while loops, etc. which is frowned upon in Scala.)
import scala.annotation.tailrec
def duplicate(s: Array[Int]): Boolean = {
// Helper function to search the array for matches to element at i
#tailrec // Indicates function is tail recursive.
def matchElement(i: Int): Boolean = {
// Helper function to search for a match in remainder of array.
#tailrec
def matchRem(j: Int): Boolean = {
// If j has reached the end of the array, we had no match.
if(j >= s.length) false
// Otherwise, does this element match the target? Match found.
else if (s(i) == s(j)) true
// Otherwise, look at the next element after j.
else matchRem(j + 1) // Recursive call
}
// If this is the last character of the array, then we can't have a match.
if(i >= s.length - 1) false
// Otherwise did we find a duplicate in the remainder of this array?
else if(matchRem(i + 1)) true
// Otherwise, perform another iteration looking at the next element.
else matchElement(i + 1) // Recursive call
}
// Start the ball rolling by looking at for duplicates of the first character.
matchElement(0)
}
This might look rather complex, at first glance, but note that it doesn't have any var declarations or while loops. Of course, this a roll-your-own solution. There are far simpler methods of achieving this using other Array functions.
In your code the variable isDupli of no use because anyway you are returning result Boolean variable. Also, you are not incrementing variable i. You can use for loop as below:
def duplicate(s: Array[Int], length: Int): Boolean ={
var result:Boolean = false; val r = Range(0,length)
for(i<-r;j<-(i+1) until length; if(s(i)==s(j))) result = true
result
}
In Scala REPL:
scala> duplicate(Array(2,2),2)
res4: Boolean = true
scala> duplicate(Array(2,3),2)
res5: Boolean = false
scala> duplicate(Array(2,3,2),3)
res6: Boolean = true
scala> duplicate(Array(2,3,4),3)
res7: Boolean = false
I'm trying to search a nested array of characters for a specific character, and then return the indices of the character from the array.
Code Snippet
def search(target: Char, arr:Array[Array[Char]]): List[Int] = {
for (i <- 0 until arr.length) { //search through first layer of array
for (j <- 0 until arr(i).length) { //search through second layer of array
if (arr(i)(j) == target) {
val x = List(i,j)
return x
} }}}
However, I'm getting an error from compilation, that says this function is returning the two type signature. Error message:
error: type mismatch;
found : Unit
required: List[Int]
for (i <- 0 until arr.length) { //search through first layer of array
^
I've found two similar threads here: found Unit: required Int. Why is the error not obvious?
and found: Unit required: Int - How to correct this?
but they don't solve the problem i'm facing: I am trying to return the List, but the compiler is getting stuck at the for loop..
Seems like there are a lot of answers already, but I think that this is the most idiomatic way to approach the problem:
The Code
def search(target: Char, arr: Array[Array[Char]]): List[(Int, Int)] = {
val indices = for{
(a, i) <- arr.iterator.zipWithIndex
(c, j) <- a.iterator.zipWithIndex
if( c == target )
} yield i -> j
indices.toList
}
The Explanation
In scala, for-comprehensions are nestable, so you can take care of any degree of nested arrays by simply adding another x <- y line. You can introduce filtering with an if statement inside of the for{...}.
In the comprehension, a is the ith array inside arr, where i is the first index. c is the jth character inside a, where j is the second index. I use iterator so that indices can be evaluated on the fly, without needing to copy the arrays behind the scenes because of the for-comprehension. At the end, I call toList to evaluate the results of the indices iterator into a list.
The return type, List[(Int, Int)] is a list of pairs. It makes more sense to return List( (1,2), (3,4) ) if you found your target at i=1, j=2 and i=3, j=4 than to return List(1,2,3,4).
General Thoughts
Try to avoid using return in scala. You can usually handle your collections with an iterator-like approach, using yield, and then evaluate the result by calling a toList or toMap or toWhatever.
The scala collections API is very helpful for many of these cases, too. In the case where you just want the first item that matches a condition, you can use myCollection.find(...). Explore the scala docs to see the huge variety of convenient functions that are already available to you.
I would suggest using a less Java-like approach altogether. I'm not entirely sure what your function is supposed to do, but if you want a list of all (x, y) indices of the match within the nested array, you could do something like this:
def search(target: Char, array: Array[Array[Char]]): Seq[(Int, Int)] = {
array.zipWithIndex.filter(_._1.contains(target)).map { xa =>
xa._1.zipWithIndex.filter(_._1 == target).map(xb => (xa._2, xb._2)).toSeq
}.flatten.toSeq
}
which behaves like this:
val t = Array(
Array('a', 'b', 'c'),
Array('b'), Array('c', 'a'),
Array('a', 'a', 'x', 'a')
)
println(search('a', t))
=> ((0,0), (2,1), (3,0), (3,1), (3,3))
Here is my solution to find the first index of a element in a two-dimension array:
(replace collectFirt to collect, if you wan to find all indexes)
def search[T](target: T, arr: Array[Array[T]]): List[Int] =
arr.indices.collectFirst{
case k if arr(k).contains(target) =>
List(k, arr(k).indexWhere(_ == target))
}.getOrElse(Nil)
Test:
scala> val t = Array(
| Array('a', 'b', 'c'),
| Array('b'),
| Array('c', 'a'),
| Array('a', 'a', 'x', 'a')
| )
scala> println(search('a', t))
List(0, 0)
scala> println(search('x', t))
List(3, 2)
scala> println(search('e', t))
List()
You only return a List if a particular condition is met (arr(i)(j) == target). You have to define a return value for the case that the for comprehensions run through. E.g.
def search(target: Char, arr:Array[Array[Char]]): List[Int] = {
for (i <- 0 until arr.length) { //search through first layer of array
for (j <- 0 until arr(i).length) { //search through second layer of array
if (arr(i)(j) == target) {
val x = List(i,j)
return x
}
}
}
Nil // not found
}
The for loop itself would return Unit if the second array is empty or the if expression evaluates to false. You could rewrite it so it returns null if it nevers gets to the code after the if-expression.
I would leave out the assignment of x too, there's really no point.
def search(target: Char, arr:Array[Array[Char]]): List[Int] =
{
for (i <- 0 until arr.length)
{ //search through first layer of array
for (j <- 0 until arr(i).length)
{ //search through second layer of array
if (arr(i)(j) == target)
{
return List(i,j)
}
}
}
Nil
}
Btw this could probably be rewritten with a more functional approach but that goes beyond the scope of this question.
I never thought I would be asking such a simple question but how do I update array element in scala
I have declared inner function inside my Main object and I have something like this
object Main
{
def main(args: Array[String])
{
def miniFunc(num: Int)
{
val myArray = Array[Double](num)
for(i <- /* something*/)
myArray(i) = //something
}
}
}
but I always get an exception, Could someone explain me why and how can I solve this problem?
Can you fill in the missing details? For example, what goes where the comments are? What is the exception? (It's always best to ask a question with a complete code sample and to make it clear what the problem is.)
Here's an example of Array construction and updating:
scala> val num: Int = 2
num: Int = 2
scala> val myArray = Array[Double](num)
myArray: Array[Double] = Array(2.0)
scala> myArray(0) = 4
scala> myArray
res6: Array[Double] = Array(4.0)
Perhaps you are making the assumption that num represents the size of your array? In fact, it is simply the (only) element in your array. Maybe you wanted something like this:
def miniFunc(num: Int) {
val myArray = Array.fill(num)(0.0)
for(i <- 0 until num)
myArray(i) = i * 2
}