在Kotlin中使用嵌套for循环导航多维数组

时间:2018-03-20 15:18:47

标签: arrays for-loop multidimensional-array kotlin

我经常浏览像素的二维图像矩阵或三维体积数据集。通常,底层数据结构是某种原始类型的一维数组,如DoubleInt。多维特性由嵌套的for循环导航,如下图所示。

鉴于Kotlin目前不支持典型的C和类似Java的for循环结构,似乎有一些失去灵活性。我想知道是否有一个聪明的迭代器或Kotlin语法来使它更优雅。

在下面的Java中,我们能够通过将主索引i嵌入到for循环中来简洁地捕获整个迭代,并且只涉及隐式增量操作,这些操作可能是计算上有效的(与除法和模数相比) ...

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;
        }
    }
}

在Kotlin中,我发现了一个解决方案,其中索引i被迫在循环块之外具有范围。此外i++线有点埋没并与环结构分离。我在这种情况下缺少优雅的Kotlin语法,例如“建造者”,没有分号等等。我谦卑地认为这是因为for循环流量控制结构的表现力较差。科特林。不可否认,这并不重要,但更令人失望。

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 个答案:

答案 0 :(得分:2)

简单的方法

您可以根据偏移计算索引......

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()
        }
    }
}

包装方式

您可以包装数组,简化访问...

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()
        }
    }
}

答案 1 :(得分:1)

这是在Kotlin中创建数组的一种方法,不使用i(或for循环):

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

答案 2 :(得分:0)

以下是我提到的涉及除法和模数的答案

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