#kotlin #initialization #set
#kotlin #инициализация #набор
Вопрос:
У меня есть набор ячеек
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)
}
}
}
Существует ли более идиоматичный (функциональный) способ инициализации набора?
В идеале я хотел бы, чтобы набор был неизменяемым, потому что после этой инициализации его никогда не следует изменять.
Ответ №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) } }
Я думаю, что первый вариант более удобочитаем.
Ответ №2:
К сожалению, нет конструктора или функции верхнего уровня, чтобы упростить создание набора, следующего определенной логике, но если у вас уже есть список, вы можете превратить его в Set
using 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()
Ответ №3:
Вы можете сделать это
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()
}
затем в вашем блоке инициализации
lateinit var board: Set<Cell>
init {
board = initBoard(width)
}