Scala Array Slicing with Tuple - arrays

I try to slice an 1D Array[Double] using the slice method. I've written a method which returns the start and end index as a tuple (Int,Int).
def getSliceRange(): (Int,Int) = {
val start = ...
val end = ...
return (start,end)
}
How can I use the return value of getSliceRange directly?
I tried:
myArray.slice.tupled(getSliceRange())
But this gives my a compile-Error:
Error:(162, 13) missing arguments for method slice in trait IndexedSeqOptimized;
follow this method with `_' if you want to treat it as a partially applied function
myArray.slice.tupled(getSliceRange())

I think the problem is the implicit conversion from Array to ArrayOps (which gets slice from GenTraversableLike).
val doubleArray = Array(1d, 2, 3, 4)
(doubleArray.slice(_, _)).tupled
Function.tupled[Int, Int, Array[Double]](doubleArray.slice)
(doubleArray.slice: (Int, Int) => Array[Double]).tupled

Two options here, the first one is to call your function twice:
myArray.slice(getSliceRange()._1, getSliceRange()._2)
or to save your Tuple beforehand:
val myTuple: (Int, Int) = getSliceRange()
myArray.slice(myTuple._1, myTuple._2)
Edit: I leave this here just in case but Peter Neyens posted the expected answer.

Related

Type Mismatch in scala, Array[Int] and Array[Option[Int]]

First, I am new to Scala, So apologies if the following question is too simple.
I have written the following code to the find the values of the keys that I supply in an array from the map.
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) : Array[Int] = {
return inputArray.map(x => inputMap.get(x))
}
I got the following error,
type mismatch;
found : Array[Option[Int]]
required: Array[Int]
return inputArray.map(x => inputMap.get(x))
Question:
1) Can anyone explain what is Option[Int]?
2) What is my mistake here ?
Thanks in advance.
Option is Scala's option type (also called a nullable type). It represents a case where the value may not exist.
Consider a map that doesn't contain a requested key. How would you handle a request for the key? One option is to result in an error, such as by throwing an exception. Another is to return a special value that indicates there is no value. Map.get does the latter, using Option as the special type and None as the value. This means the return type of Map.get isn't the value type of the map (Int), but Option applied to the value type (Option[Int]).
To correct the type declaration, change the return type:
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) : Array[Option[Int]] = {
inputArray.map(x => inputMap.get(x))
}
You can leave out the return type of stringToCountMap and let type inference handle it:
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) = {
inputArray.map(x => inputMap.get(x))
}
As a consequence, missing keys from the input map get carried through:
scala> stringToCountMap(Array("a", "def"), Map("a" -> 1, "bc" -> 2))
res0: Array[Option[Int]] = Array(Some(1), None)
Option[T] is a wrapper around a value of type T. Its purpose is to prevent NullPointerException, that you might know from Java. A value of type Option[T] might either be None, which, as the name implies is an object that represents nothing, or it might be Some(x: T), which represents an existing value.
inputMap(x) returns an Option[Int], since you have no guarantee that the x key exists in inputMap. If it does, it returns Some(value: Int), else it returns None.
Calling stringToCountMap(Array("a", "b", "c"), Map("a" -> 1, "c" -> 2)) results in Array(Some(1), None, Some(2))
If you want an Array[Int] instead, you might do something like inputArray.map(x => inputMap.getOrElse(x, 0)).get. The getOrElse method has two parameters, where the first one is the key, and the second one is the default value. inputArray.map(x => inputMap.get(x).getOrElse(0)) has the same effect, since calling getOrElse(value) on an Option either unwraps the Some object, or returns the default value.
Now, stringToCountMap(Array("a", "b", "c"), Map("a" -> 1, "c" -> 2)) results in Array(1, 0, 2).
You might also want to omit the keys missing in the input array. In that case, you might do inputArray.flatMap(x => inputMap.get(x)). flatMap is a function similar to map, but it returns strictly, as the name implies, flat collections. For example, calling flatMap(x => x) on an Array[Array[Int]] would return an Array of all the values in the 2D array in a single row.
Here, Option is a collection, as well. If it is of type Some, it contains a single value, if it is None, it is an empty collection. Thus, in the resulting array you would only have the values of the keys present in the map, and the keys not present in the map are skipped.
Now, stringToCountMap(Array("a", "b", "c"), Map("a" -> 1, "c" -> 2)) results in Array(1, 2).
First, there is no need to use 'return' in scala to return any value.
def stringToCountMap(inputArray: Array[String], inputMap:Map[String,Int]) = {
inputArray.map(x => inputMap.get(x))
}
When you get the value of key from Map, It returns result in Option.
For example:
scala> val map = Map(1-> "a",2 -> "b")
map: scala.collection.immutable.Map[Int,String] = Map(1 -> a, 2 -> b)
scala> map.get(1)
res0: Option[String] = Some(a)
scala> map.get(3)
res1: Option[String] = None
When you try to get the value of key, which does not exist. In java, you have encountered with NullPointerException. So when there is no value, it returns None to avoid exception.
For more info refer
In your method, you have given return type as Array[Int] but function returns Array[Option[Int]] that's why it throws compilation error.

Scala allocate sequential index array

In scala I would like to dynamically allocate an array of sequential index values.
In R it is simply maxindex = 10 then array = 1:maxindex which returns 1,2,3,4,5,6,7,8,9,10
Is it possible to do this in scala?
You should try Range method:
Range(val start : Int, val end : Int, val step : Int)
You could use it like this:
var yourArray = range(1, 10, 1)
That will return an array like you want: 1,2,3,4,5,6,7,8,9,10
Or even more simple:
var yourArraySimpler = 1 until 11
Take a look at the documentation. From the link:
The Range class represents integer values in range [start;end) with
non-zero step value step. Sort of acts like a sequence also (supports
length and contains).
It is as simple as:
val arr = 1 to 10
which uses an implicit conversion to generate a Range as described in #cacho's answer. Range is a subclass of Seq, but you can call .toArray on it if you specifically need an array.

How to create an empty array in kotlin?

I'm using Array(0, {i -> ""}) currently, and I would like to know if there's a better implementation such as Array()
plus, if I'm using arrayOfNulls<String>(0) as Array<String>, the compiler will alert me that this cast can never succeed. But it's the default implementation inside Array(0, {i -> ""}). Do I miss something?
As of late (June 2015) there is the Kotlin standard library function
public fun <T> arrayOf(vararg t: T): Array<T>
So to create an empty array of Strings you can write
val emptyStringArray = arrayOf<String>()
Just for reference, there is also emptyArray. For example,
var arr = emptyArray<String>()
See
doc
Array.kt
Empty or null? That's the question!
To create an array of nulls, simply use arrayOfNulls<Type>(length).
But to generate an EMPTY array of size length, use:
val arr = Array(length) { emptyObject }
Note that you must define an emptyObject properly per each data-type (beacause you don't want nulls). E. g. for Strings, emptyObject can be "". So:
val arr = Array(3) { "" } // is equivalent for: arrayOf("","","")
Here is a live example. Note that the program runs with two sample arguments, by default.
null array
var arrayString=Array<String?>(5){null}
var nullArray= arrayOfNulls<String>(5)
As mentioned above, you can use IntArray(size) or FloatArray(size).
I found two ways to create an empty array, the second way without a lambda:
var arr = Array (0, { i -> "" })
var arr2 = array<String>()
Regarding Kotlin's null strings, this is not allowed. You have to use String? type to allow strings to be null.
Use:
#JvmField val EMPTY_STRING_ARRAY = arrayOfNulls<String>(0)
It returns an 0 size array of Strings, initialized with null values.
1. Wrong:
#JvmField val EMPTY_STRING_ARRAY = emptyArray<String>()
It returns arrayOfNulls<String>(0)
2. Wrong:
#JvmField val EMPTY_STRING_ARRAY = arrayOf<String>()
It returns an array containing the Strings.
Simplest way to initialise array and assigning values :
val myArray: Array<String> = Array(2) { "" }
myArray[0] = "Java"
myArray[1] = "Kotlin"

Using the apply / (array subscripting) method in a builder pattern

Given a trivial function returning an array:
scala> def methodReturnsArray() = { Array(1.0, 2.0) }
methodReturnsArray: ()Array[Double]
We can go ahead and invoke the function:
scala> val myarr = methodReturnsArray
myarr: Array[Double] = Array(1.0, 2.0)
scala> myarr(0)
res21: Double = 1.0
However, it is not possible to use the apply ( / array index semantics) directly:
scala> methodReturnsArray(0)
<console>:53: error: too many arguments for method methodReturnsArray: ()Array[Double]
methodReturnsArray(0)
^
The request is to explain why that were not possible as given. Secondarily: is there some way to get an "inline" invocation. I.e. not requiring to separate out the steps: s
(a) invoke the method and
(b) access the specific element of the array (via apply())
on separate statements.
Aha! Seconds after posting this I arrived at the answer: need to include the parens on the function call: i.e methodReturnsArray () (0) :
scala> methodReturnsArray()(0)
res22: Double = 1.0

incredible implicit Array conversion in scala

According to Scaladoc, there is no method named map in Array class, but there is an implicit function implicit def intArrayOps (xs: Array[Int]): ArrayOps[Int] defined in scala.Predef. So you can apply map on Array(1,2,3,4) if you like. But What I am confused about is that the map result is of type Array[Int], not ArrayOps[Int]. Here is my test:
scala> val array = Array(1,2,3,4)
array: Array[Int] = Array(1, 2, 3, 4)
scala> array.map(x => x)
res18: Array[Int] = Array(1, 2, 3, 4)
scala> res18.isInstanceOf[Array[Int]]
res19: Boolean = true
scala> res18.isInstanceOf[scala.collection.mutable.ArrayOps[Int]]
warning: there wre 1 unchecked warnings; re-run with -unchecked for details
res20: Boolean = false
It indeed returns an array, as intended and as is convenient, there is no reason you would need an ArrayOps, it is intended only to provide extra methods to arrays. The doc is wrong.
The routine is actually not implemented in ArrayOps. As most collection methods, it is inherited from TraversableLike. And you see two map methods in the doc:
def map [B] (f: (T) ⇒ B): ArrayOps[B]
def map [B, That] (f: (T) ⇒ B)(implicit bf: CanBuildFrom[Array[T], B, That]): That
Only the second one exists (inherited from TraversableLike). It is intended to allow implementation of map in just one place (traversable like) while allways giving the best possible behavior. For instance, a String is a of Seq[Char], if you map with a function from character to character, you get a String, but if you map from collection to say Int, the result cannot be a String and it will just be a Seq. This is explained in much detail in the paper fighting the bit rot with types.
However, this makes for a very complex signature, which does not reflect the simplicity of using the method, and makes very poor documentation most of the time (you normally would have to chase to which CanBuildFrom in implicit scope would work). This was discussed in this most famous scala question of stack overflow. So the tool scaladoc was extended so that a simpler entry, corresponding to intended usage, may appear. If you look at the source of GenTraversableLike, where the routine is introduced, you will see the following in the scaladoc for map (and a similar one in many methods)
#usecase def map[B](f: A => B): $Coll[B]
Subtypes add in their doc #define Coll <className>, and map (among others) appears with the simplified signature, marked [Use case]. In the source of ArrayOps, there is a #define Coll ArrayOps where it should be Array.
You can use the REPL with the -Xprint:typer option to see what's going on. Here is the output of the map method, reformatted for easier reading:
$ scala -Xprint:typer
scala> Array(1,2,3,4).map(x => x)
[[syntax trees at end of typer]]// Scala source: <console>
// some lines deleted
private[this] val res0: Array[Int] =
scala.this.Predef.intArrayOps(scala.Array.apply(1, 2, 3, 4))
.map[Int, Array[Int]]
(( (x: Int) => x ))
(scala.this.Array.canBuildFrom[Int](reflect.this.Manifest.Int));
So simplifying for package names here is what happens:
intArrayOps(Array(1,2,3,4)) // converts to ArrayOps
.map[Int, Array[Int]] // calls map with parameter lists below
((x:Int) => x) // pass identity function as fisrt param
(Array.canBuildFrom[Int]// pass builder for Array[Int] as second param
(Manifest.Int)) // pass class manifest for Int
So there is indeed a conversion to ArrayOps (first line). It returns ArrayOps[Int].
The ArrayOps.map[Int, Array[Int]] method is then called on it. Then as didierd explain, the original signature for map - not the simplified signature - indicates that the return type inferred will be Array[Int]

Resources