Assigning one value to many elements of an array in Scala - scala

I have some experience with R language and now I wanted to try Scala language. In R language I can assign one value to many elements of a vector, e.g.
(xs <- 1:10)
#[1] 1 2 3 4 5 6 7 8 9 10
k <- 3
xs[1:k] <- xs[k+1]
xs
# 4 4 4 4 5 6 7 8 9 10
It assigns value of k+1 element to all elements of indices from 1 to k. Is it also possible to do it without a loop in Scala (I mean Array in Scale)? I know there is slice method, but it only returns values of an Array, one cannot modify elements of the Array using this method.
What is even more, should I use Array or ArrayBuffer if I only want to change values of elements and I do not want to add/remove elements from a collection?

Check out the java.util.Arrays.fill methods.
scala> val xs = (1 to 9).toArray
xs: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> val k = 6
k: Int = 6
scala> java.util.Arrays.fill(xs, 0, k, xs(k))
scala> xs
res10: Array[Int] = Array(7, 7, 7, 7, 7, 7, 7, 8, 9)

For your second question, if not resizing the collection but editing the elements, stick with array. ArrayBuffer is much like the Java ArrayList, it resizes it self when it needs to, so insertion is amortized constant, not just constant.
For your first question, I'm not aware of any method in the collections library that would allow you to do this. It's obviously syntactic sugar for looping, so if you really care (do you really find yourself needing to do this often?), you can define an implicit class and yourself define a method which loops, and then use that. Write a comment if you would like to see example of such code, otherwise try doing it yourself, it's gonna be good training.

Scala has the Range class. You can convert the Range to an Array if you wish.
scala> val n = 10
n: Int = 10
scala> Range(1,n)
res22: scala.collection.immutable.Range = Range(1, 2, 3, 4, 5, 6, 7, 8, 9)
scala> res22.toArray
res23: Array[Int] = Array(1, 2, 3, 4, 5, 6, 7, 8, 9)
│
ArrrayBuffer has constant time update and would be good for updating values.

Related

Scala console doesn't display the elements generated in range sequence

I am learning Scala language and using Intellij editor. I was exploring the range sequence in Scala console. With the below code, it generates a range sequence, but it is not displaying the elements. I tried this in Eclipse as well, but didn't get the elements. Is there any option available to make the elements of the range sequence to be displayed?
I tried to generate a range sequence from 1 to 10
scala> 1 to 10
res15: scala.collection.immutable.Range.Inclusive = Range 1 to 10
scala> res15
res16: scala.collection.immutable.Range.Inclusive = Range 1 to 10
I expected the elements in the range sequence to be displayed.
Ranges in Scala are not like arrays or lists in other languages - their elements are not all stored in memory. Instead, they are abstract sequences that are defined by 3 values - their start, their end, and the stepping value: https://docs.scala-lang.org/overviews/collections-2.13/concrete-immutable-collection-classes.html#ranges
If you want to see your values, you can convert your range to a list:
scala> (1 to 10).toList
res1: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8, 9, 10)

How to remove duplicates from list without using in inbuilt libraries such as distinct, groupBy(identity), toSet.. Etc

I wanted to write a Scala program that takes command-line args as list input and provide the output list without duplicates.
I want to know the custom implementation of this without using any libraries.
Input : 4 3 7 2 8 4 2 7 3
Output :4 3 7 2 8
val x= List(4, 3, 7, 2, 8, 4, 2, 7, 3)
x.foldLeft(List[Int]())((l,v)=> if (l.contains(v)) l else v :: l)
if you can't use contains you can do another fold
x.foldLeft(List[Int]())((l,v)=> if (l.foldLeft(false)((contains,c)=>if (c==v ) contains | true else contains | false)) l else v :: l)
Here's a way you could do this using recursion. I've tried to lay it out in a way that's easiest to explain:
import scala.annotation.tailrec
#tailrec
def getIndividuals(in: List[Int], out: List[Int] = List.empty): List[Int] = {
if(in.isEmpty) out
else if(!out.contains(in.head)) getIndividuals(in.tail, out :+ in.head)
else getIndividuals(in.tail, out)
}
val list = List(1, 2, 3, 4, 5, 4, 3, 5, 6, 0, 7)
val list2 = List(1)
val list3 = List()
val list4 = List(3, 3, 3, 3)
getIndividuals(list) // List(1, 2, 3, 4, 5, 6, 0, 7)
getIndividuals(list2) // List(1)
getIndividuals(list3) // List()
getIndividuals(list4) // List(3)
This function takes two parameters, in and out, and iterates through every element in the in List until it's empty (by calling itself with the tail of in). Once in is empty, the function outputs the out List.
If the out List doesn't contain the value of in you are currently looking at, the function calls itself with the tail of in and with that value of in added on to the end of the out List.
If out does contain the value of in you are currently looking at, it just calls itself with the tail of in and the current out List.
Note: This is an alternative to the fold method that Arnon proposed. I personally would write a function like mine and then maybe refactor it into a fold function if necessary. I don't naturally think in a functional, fold-y way so laying it out like this helps me picture what's going on as I'm trying to work out the logic.

Scala array understanding?

I have tried below array example in my scala console.Declared immutable array, tried to change the array index values.Immutable should not allow modifying the values. I don't understand whats happening .can anyone explain, please.
val numbers=Array(1,2,3)
numbers(0)=5
print numbers
res1: Array[Int] = Array(5, 2, 3)
Thanks!
Declaring something as a val does not make it immutable. It merely prevents reassignment. For example, the following code would not compile:
val numbers = Array(1, 2, 3)
numbers = Array(5, 2, 3)
Notice that what changes in the above code is not something about the array object's internal state: what changes is the array that the name numbers references. At the first line, the name numbers refers to the array Array(1, 2, 3), but in the second line we try reassign the name numbers to the array Array(5, 2, 3) (which the compiler won't allow, since the name numbers is declared using val).
In contrast, the below code is allowed:
val numbers = Array(1, 2, 3)
numbers(0) = 5
In this code, the name numbers still points to the same array, but it's the internal state of the array that has changed. Using the val keyword for the name of an object cannot prevent that object's internal state from changing, the val keyword can only prevent the name from being reassigned to some other object.
You did not declare an immutable array. Array in Scala is mutable.
Where you might be confused is what exactly val vs var means. val does not make an object immutable, it makes the reference immutable so you can't reassign a different array to your variable, but you can still modify the contents since it is a mutable object.
If you want immutability you need to use val together with an immutable object like Vector or List.
Maybe your understanding of scala Array is not right.
Please pay attention to the following principle!
Arrays preserve order, can contain duplicates, and are mutable.
scala> val numbers = Array(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
numbers: Array[Int] = Array(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
scala> numbers(3) = 10
Lists preserve order, can contain duplicates, and are immutable.
scala> val numbers = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
numbers: List[Int] = List(1, 2, 3, 4, 5, 1, 2, 3, 4, 5)
scala> numbers(3) = 10
<console>:9: error: value update is not a member of List[Int]
numbers(3) = 10

Create 2D array and store value into each element of that array in Scala

I am working on a Scala exercise which asks me to create a 2D array of 4 rows and 5 columns and store the row index+column index+5 in each element. Also I have to sum the array by rows and then by columns and print the rows total and the columns total.I am so confused and I only know how to create an empty array.
val matrix = Array.ofDim[Int](4, 5)
Can you teach me how to do the rest of this exercise?
I will not tell you "the rest of the exercise" but I will try to show one way to create a 2D collection, like an array in this case:
val matrix1D = for {
rowIndex <- (0 until 4).toArray
colIndex <- (0 until 5).toArray
} yield rowIndex + colIndex + 5
Where
scala> :t matrix1D
Array[Int]
Now the result of this for-comprehension is the 1D version of your 2D array.
EDIT
I could probably give you few more hints:
scala> (0 to 11).toArray.grouped(4).toArray
res10: Array[Array[Int]] = Array(Array(0, 1, 2, 3), Array(4, 5, 6, 7), Array(8, 9, 10, 11))
scala> .transpose
res11: Array[Array[Int]] = Array(Array(0, 4, 8), Array(1, 5, 9), Array(2, 6, 10), Array(3, 7, 11))
EDIT
After you create matrix2D from matrix1D:
val matrix2D = matrix1D.??????????????????
Where
scala> :t matrix2D
Array[Array[Int]]
To print it out, you could simply use mkString:
scala> matrix2D.map(_.mkString("\t")).mkString("\n")
res32: String =
5 6 7 8 9
6 7 8 9 10
7 8 9 10 11
8 9 10 11 12

Using Stream as a substitute for loop

scala> val s = for(i <- (1 to 10).toStream) yield { println(i); i }
1
s: scala.collection.immutable.Stream[Int] = Stream(1, ?)
scala> s.take(8).toList
2
3
4
5
6
7
8
res15: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8)
scala> s.take(8).toList
res16: List[Int] = List(1, 2, 3, 4, 5, 6, 7, 8)
Looks like Scala is storing stream values in memory to optimize access. Which means that Stream can't be used as a substitute for imperative loop as it will allocate memory. Things like (for(i <- (1 to 1000000).toStream, j <- (1 to 1000000).toStream) yield ...).reduceLeft(...) will fail because of memory. Was it wrong idea to use streams this way?
You should use Iterator instead of Stream if you want a loop-like collection construct. Stream is specifically for when you want to store past results. If you don't, then, for instance:
scala> Iterator.from(1).map(x => x*x).take(10).sum
res23: Int = 385
Methods continually, iterate, and tabulate are among the more useful ones in this regard (in the Iterator companion object).