在Kotlin中初始化集的更惯用的方法?

时间:2019-04-22 20:12:10

标签: kotlin initialization set

我有一组细胞
data class Cell(val i: Int, val j: Int)
像这样在我的班上初始化的

protected val board = mutableSetOf<Cell>()
init {
    for (i in 1..width) {
        for (j in 1..width) {
            board += Cell(i, j)
        }
    }
}

是否有更惯用的(功能性的)方式初始化集合?
理想情况下,我希望该集合是不可变的,因为在初始化之后,永远不要更改它。

3 个答案:

答案 0 :(得分:1)

您可以定义一个扩展,该扩展接受一个转换器以将组合作为一对整数,然后将其映射到Cell。例如:

inline fun <R> IntRange.combine(block: (Int, Int) -> R): Set<R> {
    return flatMap { x -> map { y -> block(x, y) } }.toSet()
}

然后您可以使用以下代码进行初始化:

protected val board = (1..width).combine { x, y -> Cell(x, y) }

或简单地:

protected val board = (1..width).flatMap { i -> (1..width).map { j -> Cell(i, j) } }

我认为前者更具可读性。

答案 1 :(得分:1)

不幸的是,没有构造函数或顶级函数可以使遵循特定逻辑的集合的创建变得容易,但是如果您已经有了列表,则可以使用Set将其转换为toSet()

无论如何,我都会分开创建组合列表和创建Cell实例的逻辑。

// extension property on IntRange to create all possible combinations
val IntRange.combinations get() = flatMap { i -> map { j -> i to j }}

val set = (1..5)
             .combinations
             .map { (i, j) -> Cell(i, j) }
             .toSet()

添加:

如果您为Cell创建一个辅助构造函数,它需要一个Pair,如下所示:

data class Cell(val i: Int, val j: Int) {
    constructor(pair: Pair<Int, Int>): this(pair.first, pair.second)
}

您可以将代码缩短为:

val set = (1..5).combinations.map(::Cell).toSet()

答案 2 :(得分:0)

您可以做到

fun initBoard(width: Int): Set<Cell> {
    return List<Cell>(width * width) { index ->
            val i = index / width
            val j = index % width
            Cell(i + 1, j + 1)
    }.toSet()
}

然后在您的init块中

lateinit var board: Set<Cell>

init {
    board = initBoard(width)
}