strange ArrayBuffer behavior - arrays

Can someone please explain to me why the padTo method of ArrayBuffer doesn't work as I would expect it to? In this example, I would expect the array created by toArray to have a length of 10.
scala> val b = new scala.collection.mutable.ArrayBuffer[Byte]
b: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer()
scala> b.append(2)
scala> b
res1: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(2)
scala> b.append(2)
scala> b
res3: scala.collection.mutable.ArrayBuffer[Byte] = ArrayBuffer(2, 2)
scala> b.padTo(10,0)
res4: scala.collection.mutable.ArrayBuffer[AnyVal] = ArrayBuffer(2, 2, 0, 0, 0, 0, 0, 0, 0, 0)
scala> b.toArray
res5: Array[Byte] = Array(2, 2)

Because padTo returns a new sequence (it doesn't mutate the existing one):
Try
var c = b.padTo(10,0)
c.toArray
See also: https://issues.scala-lang.org/browse/SI-2257

If you look at the documentation, you'll see the difference:
def append (elems: A*): Unit
Use case (append): Appends the given elements to this buffer.
def padTo (len: Int, elem: A): ArrayBuffer[A]
Use case (padTo): Appends an element value to this arraybuffer until a given target length is reached.
Append returns Unit, while padTo returns new ArrayBuffer.

From scaladoc:
returns: a new collection of type That consisting of all elements of
this arraybuffer followed by the minimal number of occurrences of elem
so that the resulting collection has a length of at least len.
So, b, even mutable, does not changes.

Related

How to apply a 0-ary anonymous function to an array

Having an Array of Int, and a function without parameters:
scala> val a = new Array[Int](5)
a: Array[Int] = Array(0, 0, 0, 0, 0)
scala> def f(): Int = 1
f: ()Int
I want to apply the function f() to the array with map() or transform(). I tried the following approaches.
First approach
scala> a.map(f)
<console>:14: error: type mismatch;
found : () => Int
required: Int => ?
a.map(f)
^
It fails, which I don't really understand why.
Second approach
scala> a.map(x => f)
res1: Array[Int] = Array(1, 1, 1, 1, 1)
This one works. However, I'm declaring a parameter x that I don't use in the right side of =>. It seems that anonymous functions need at least one parameter.
Is it correct not to use x?
Is it even a bad functional style?
Practical example
To give an example on why one would use that. Imagine I have an array that at some moment I want to mutate to have random values:
val a = new Array[Int](5)
// ...
a.transform(x => random())
Try using underscore for ignored argument like so
a.map(_ => f)
which outputs
res0: Array[Int] = Array(1, 1, 1, 1, 1)
Just for the sake of playing with transformations:
def to1[A, B](f: () => B): A => B = (_: A) => f()
val a = new Array[Int](5)
def f(): Int = 1
a.map(to1(f))
Regarding your example, consider using fill:
val b = Array.fill[Int](a.size)(myArgLessFunc())

Element-wise sum of arrays in Scala

How do I compute element-wise sum of the Arrays?
val a = new Array[Int](5)
val b = new Array[Int](5)
// assign values
// desired output: Array -> [a(0)+b(0), a(1)+b(1), a(2)+b(2), a(3)+b(3), a(4)+b(4)]
a.zip(b).flatMap(_._1+_._2)
missing parameter type for expanded function
Try:
a.zip(b).map { case (x, y) => x + y }
When you use an underscore as a placeholder in a function definition, it can only appear once (for each function argument position, that is, but in this case flatMap takes a Function1, so there's only one). If you need to refer to an argument more than once, you can't use the placeholder syntax—you'll need to give the argument a name.
As the other answers point out, you can use .map { case (x, y) => x + y } or the tuple accessor version, but it's also worth noting that if you want to avoid a bunch of tuple allocations in an intermediate collection, you can write the following:
scala> (a, b).zipped.map(_ + _)
res5: Array[Int] = Array(0, 0, 0, 0, 0)
Here zipped is a method that's available on pairs of collections that has a special map that takes a Function2, which means the only tuple that gets created is the (a, b) pair. The extra efficiency probably doesn't matter much in most cases, but the fact that you can pass a Function2 instead of a function from pairs means the syntax is often a little nicer as well.
// one D Array
val x = Array(1, 2, 3, 40, 55)
val x1 = Array(1, 2, 3, 40, 55)
x.indices.map(i=>x(i)+ x(i) )
// TWo D Array
val x1= Array((3,5), (5,7))
val x = Array((1,2), (3,4))
x.indices.map(i=>( x(i)._1 + x1(i)._1, x(i)._2 + x1(i)._2))

Extract string of "length x breadth" into different arrays

I have a string with with multiple length and breadth in the format length x breadth separated by commas like
300x250, 720x220, 560x80
I will like to convert this into two separate arrays one containing only length and another only breadth.
Expected output
length = Array(300,720, 560)
breadth = Array(250, 220, 80)
Any novel way to achieve it?
Using unzip over tupled values, as follows,
val dims = "300x250, 720x220, 560x80"
dims.split("\\W+").map {
s => val Array(a,b,_*) = s.split("x")
(a.toInt,b.toInt) }.unzip
Note the first split fetches words without need for trimming additional blank characters. In the second split we extract the first and second elements of the resulting Array.
try this
scala> "300x250, 720x220, 560x80"
res0: String = 300x250, 720x220, 560x80
scala> res0.split(", ").map(_.split("x")(0).toInt)
res1: Array[Int] = Array(300, 720, 560)
scala> res0.split(", ").map(_.split("x")(1).toInt)
res2: Array[Int] = Array(250, 220, 80)
val str = "300x250, 720x220, 560x80"
val regex = "(\\d+)x(\\d+)".r
val result = for {
pair <- str.split(",\\s+").toList
m <- regex.findAllMatchIn(pair)
} yield (m.group(1).toInt, m.group(2).toInt)
val (length, breadth) = result.unzip

Faster way to make a zeroed array in Scala

I create zeroed Arrays in Scala with
(0 until Nrows).map (_ => 0).toArray but is there anything faster ? map is slow.
I have the same question but with 1 instead of O, i.e. I also want to accelerate (0 until Nrows).map (_ => 1).toArray
Zero is the default value for an array of Ints, so just do this:
val array = new Array[Int](NRows)
If you want all those values to be 1s then use .fill() (with thanks to #gourlaysama):
val array = Array.fill(NRows)(1)
However, looking at how this works internally, it involves the creation of a few objects that you don't need. I suspect the following (uglier) approach may be quicker if speed is your main concern:
val array = new Array[Int](NRows)
for (i <- 0 until array.length) { array(i) = 1 }
For multidimensional arrays consider Array.ofDim, for instance,
scala> val a = Array.ofDim[Int](3,3)
a: Array[Array[Int]] = Array(Array(0, 0, 0), Array(0, 0, 0), Array(0, 0, 0))
Likewise,
scala> val a = Array.ofDim[Int](3)
a: Array[Int] = Array(0, 0, 0)
In the context here,
val a = Array.ofDim[Int](NRows)
For setting (possibly nonzero) initial values, consider Array.tabulate, for instance,
scala> Array.tabulate(3,3)( (x,y) => 1)
res5: Array[Array[Int]] = Array(Array(1, 1, 1), Array(1, 1, 1), Array(1, 1, 1))
scala> Array.tabulate(3)( x => 1)
res18: Array[Int] = Array(1, 1, 1)

Compare size of 2 Arrays in Scala

If I have 2 arrays, how do I compare them and return the size of the smallest one? Here is what I mean:
val a = Array(1,2,3)
val b = Array(1,2,3,4)
is there some operator that I could call to compare the sizes of both and return 3, since Array a is smaller and has 3 elements?
scala> val a = Array(1,2,3)
a: Array[Int] = Array(1, 2, 3)
scala> val b = Array(1,2,3,4)
b: Array[Int] = Array(1, 2, 3, 4)
scala> math.min(a.length, b.length)
res0: Int = 3
A more generic approach, assuming you want to compare Sequences of the same type.
def getSmallerCollectionSize[T](a:Seq[T],b:Seq[T]) =
Math.min(a.size, b.size)
scala> val a = Array(1,2,3)
a:Array[Int] = Array(1,2,3)
scala> val b = Array(1,2,3,4)
b:Array[Int] = Array(1,2,3,4)
scala> a.size min b.size
res0: Int = 3
The size method gets the size of the Array and min is a comparator function between the two sizes. As with any function taking two parameters, you can call it by putting the function name between the parameters.
min is doing an implicit conversion (a set of methods that Scala tries to apply when it encounters an object of the wrong type being used) from Int to RichInt.

Resources