Let say that I have path that goes through 4 vertices. When doing rapid prototyping I would define this in java as
double[][] path = {{1.0, 2.0}, {1.0,3.0}, {3.0,4.0}, {8.0,9.0}}
Using the arrayOf, and doubleArrayOf function the same code in Kotlin would be
val path = arrayOf(doubleArrayOf(1.0, 2.0), doubleArrayOf(1.0, 2.0), doubleArrayOf(1.0,3.0), doubleArrayOf(8.0,9.0))
Which feels a bit verbose. Is there a Kotlin way of solving this ?
Edit: The use-case is answering queries in a "REPL like" environment on numerical data i.e. think Matlab or SciPy.
In Kotlin, arrays can be created using the function arrayOf() or using an Array constructor. Arrays are stored in a sequence as per the memory location is concerned.
There are two ways to define an array in Kotlin. We can use the library function arrayOf() to create an array by passing the values of the elements to the function. Since Array is a class in Kotlin, we can also use the Array constructor to create an array.
In Kotlin, creating an IntArray of size N is simple. Use IntArray(n) or the appropriate type, as detailed thoroughly in hotkey's answer. In this case, x will be taken from index 0, y from index 1, etc. Save this answer.
As far as the stdlib goest, this is as short as it gets. You could however define a helper function yourself:
fun doubles(vararg values: Pair<Double, Double>) = values
.map { doubleArrayOf(it.first, it.second) }
.toTypedArray()
Usage:
fun main(args: Array<String>) {
val path = doubles(1.0 to 2.0, 1.0 to 3.0, 3.0 to 4.0, 8.0 to 9.0)
}
This is not the most efficient solution because it involves boxing and allocation of one temporary array and list, but if you're only prototyping this should be ok.
EDIT:
I also made a version where you can add arrays of arbitrary length:
inline fun doubles(block: DoubleArrayBuilder.() -> Unit) = DoubleArrayBuilder()
.apply(block)
.list.toTypedArray()
class DoubleArrayBuilder {
val list = mutableListOf<DoubleArray>()
fun add(vararg doubles: Double) = list.add(doubles)
}
Usage:
fun main(args: Array<String>) {
val path = doubles {
add(2.0, 3.0, 4.0)
add(2.0, 3.0, 4.0)
add(2.0, 3.0, 4.0)
}
}
arrayOf
and doubleArrayOf
and others like them, are just top level functions in stdlib. To shorten the syntax, you can easily create your own functions with scope at the top level, within a class, or even locally within a function:
By creating:
fun pathOf(vararg points: DoubleArray): Array<out DoubleArray> = points
fun pt(x: Double, y: Double) = doubleArrayOf(x,y)
This allows:
val path = pathOf(pt(1.0, 2.0), pt(1.0, 2.0), pt(1.0, 3.0), pt(8.0, 9.0))
Which now gives the nested arrays meaning for a future reader or the code. Name the function point
, pt
, xy
, or whatever suits your use case.
This code is only slightly longer than the original, and maybe more readable/meaningful than the Java:
double[][] path = {{1.0, 2.0}, {1.0, 3.0}, {3.0, 4.0}, {8.0, 9.0}}
These functions are just as efficient as using arrayOf
and doubleArrayOf
and if used repeatedly the JVM will eventually inline
them, but if you are nervous you can make them inline
yourself.
Kotlin is intended to be extended, any time you run into an issue like this think about how you can extend an API or change a function to get the readability you desire.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With