在Kotlin中展平二维数组的迭代器

时间:2018-01-06 10:34:11

标签: arrays multidimensional-array iterator kotlin

我有一个Grid类,它是2d Cell个对象数组的包装器。我希望这个类实现Iterable<Cell>接口,以便在循环中使用它并直接迭代整个单元格。有一个简单的方法吗? Kotlin是否支持yield return样式迭代器?我目前的解决方案非常详细:

override fun iterator() = object : Iterator<Cell> {
    val currentOuter = grid.iterator() // grid is object of Array<Array<Cell>>
    var currentInner = if (currentOuter.hasNext()) currentOuter.next().iterator() else arrayOf<Cell>().iterator()

    override fun next(): Cell {
        if (!hasNext()) {
            throw NoSuchElementException()
        }

        return if (currentInner.hasNext()) {
            currentInner.next()
        } else {
            currentInner = currentOuter.next().iterator()
            currentInner.next()
        }
    }

    override fun hasNext(): Boolean {
        return currentInner.hasNext() || currentOuter.hasNext()
    }
}

2 个答案:

答案 0 :(得分:4)

  

Kotlin是否支持收益返回式迭代器?

是的,通过协同程序的功能确实如此。这是一个独立的例子:

data class Cell(val d: Int)

val grid: Array<Array<Cell>> = arrayOf(arrayOf(Cell(1), Cell(2)), arrayOf(Cell(3), Cell(4)))

fun cellSequence() = buildSequence {
    grid.forEach { it.forEach { yield(it) } }
}

fun main(args: Array<String>) {
    cellSequence().forEach { println(it) }
}

虽然这个特定的问题可以通过flatMap简单地解决,但是所呈现的代码可以作为模板来编写任何类似程序的代码,例如:

fun complexCellSequence() = buildSequence {
    yield(Cell(-1))
    if (grid.size <= 2) {
        yield(Cell(2))
    }
    for (row in grid) {
        if (row.contains(Cell(1))) {
            yield(Cell(1))
        } else {
            yield(Cell(12))
            row.forEach { yield(it) }
        }
    }
}

如果没有协同程序,重写是非常不重要的。

答案 1 :(得分:2)

一个非常简单的解决方案是这样的:

val grid: Array<Array<Cell>> = ...

override fun iterator() : Iterator<Cell> = grid.flatMap { it.asList() }.iterator()