2

Quite often I am navigating a two-dimensional image matrix of pixels or a three-dimensional volumetric data set. Typically the underlying data structure is a one-dimensional array of some primitive type like Double or Int. The multi-dimensional nature is navigated through by nested for-loops as illustrated below.

Given that Kotlin does not currently support the typically C and Java-like for-loop structure, there seems some lost flexibility. I'm wondering if there is a clever iterator or Kotlin syntax to make this more elegant.

In Java below, we have the ability to capture the whole iteration concisely by embedding the master index i into the for-loops and only involving implicit increment operations which are presumably computationally efficient (compared to division and modulo)...

public static void main(String[] args) {
    int nrow=1000, ncol=1000;
    int size=nrow*ncol;
    double[] data = new double[size];

    for (int i=0, r = 0; r < nrow; r++) {
        for (int c = 0; c < ncol; c++,i++) {
            data[i]= r*c;
        }
    }
}

In Kotlin as follows, I find a solution where the index i is forced to have scope outside the loop block. Also the i++ line is somewhat buried and separated from the loop structure. I'm missing in this situation the elegant Kotlin syntax such as 'builders', no semi-colons, etc. I humbly submit that this is because the for-loop flow-control structure is less expressive in Kotlin. Admittedly, this is not critical, but more of a disappointment.

fun main(args : Array<String>) {
    val nrow = 1000
    val ncol = 1000
    val size = nrow * ncol
    val data = DoubleArray(size)

    var i = 0
    for(r in 0 until nrow) {
        for(c in 0 until ncol) {
            data[i] = (r * c).toDouble()
            i++
        }
    }
}

3 Answers 3

4

The simple way

You can calculate the index based on the offsets...

fun main(args : Array<String>) {
    val nrow = 1000
    val ncol = 1000
    val size = nrow * ncol
    val data = DoubleArray(size)

    for(r in 0 until nrow) {
        for(c in 0 until ncol) {
            data[(ncol*r) + c] = (r * c).toDouble()
        }
    }
}

The wrapper way

You can wrap the array, simplifying access...

class ArrayWrapper<T>(val height: Int, val width: Int, val default: Int) {
    private val data: Array<Any?> = Array(height, {default})
    operator fun get(x: Int, y: Int) = data[(width * y) + x] as T
    operator fun set(x: Int, y: Int, value: T) {
        data[(width * y) + x] = value
    }

    val rowIndices = (0 until width)
    val columnIndices = (0 until height)
}

fun main(args : Array<String>) {
    val nrow = 1000
    val ncol = 1000
    val data = ArrayWrapper<Double>(nrow, ncol, 0)

    for(r in data.rowIndices) {
        for(c in data.columnIndices) {
            data[r, c] = (r * c).toDouble()
        }
    }
}
Sign up to request clarification or add additional context in comments.

Comments

2

This is one way of creating your array in Kotlin, without using i (or for loops):

val data = (0 until nrow).flatMap { r ->
    (0 until ncol).map { c ->
        (r * c).toDouble()
    }
}.toDoubleArray()

Comments

0

Here is the answer I mentioned involving division and modulo

fun main(args : Array<String>) {
    val nrow = 1000
    val ncol = 1000
    val size = nrow * ncol
    val data=DoubleArray(size,{(it/ncol * it%ncol).toDouble()})
}

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.