Как перебрать список с индексом
fun main() {
val colors = listOf("red", "green", "blue")
for ((index, color) in colors.withIndex()) {
println("$index: $color")
}
colors.forEachIndexed { i, c ->
println("${i + 1}. $c")
}
for (i in colors.indices) {
println("${colors[i]} has ${colors[i].length} letters")
}
}0: red
1: green
2: blue
1. red
2. green
3. blue
red has 3 letters
green has 5 letters
blue has 4 letters| Способ | Когда удобен |
|---|---|
for ((i, x) in list.withIndex()) | обычный цикл, нужны и номер, и значение; работают break и continue |
list.forEachIndexed { i, x -> ... } | короткое действие с каждым элементом |
for (i in list.indices) | нужны соседние элементы (list[i - 1], list[i + 1]) или замена по номеру |
Номера начинаются с нуля. Для нумерации «по-человечески» выводите i + 1.
withIndex() превращает список в последовательность пар «номер — значение», а запись (index, color) сразу раскладывает каждую пару по двум переменным. Имена переменных можно выбрать любые: (i, c), (n, item).
Найти номер элемента
Если нужен не перебор, а номер одного элемента, цикл не нужен:
fun main() {
val colors = listOf("red", "green", "blue")
println(colors.indexOf("blue"))
println(colors.indexOf("black"))
println(colors.indexOfFirst { it.length > 3 })
}2
-1
1indexOf возвращает номер первого такого элемента или -1, если его нет. indexOfFirst { ... } — номер первого элемента, для которого условие верно: здесь это green, первое слово длиннее трёх букв.
Только значения
Если номер не нужен, проще без него:
fun main() {
val colors = listOf("red", "green", "blue")
for (c in colors) {
println(c)
}
}red
green
blueВ обратном порядке
fun main() {
val nums = listOf(10, 20, 30)
for (i in nums.indices.reversed()) {
println("$i: ${nums[i]}")
}
for (x in nums.reversed()) {
println(x)
}
}2: 30
1: 20
0: 10
30
20
10То же, что nums.indices.reversed(), — nums.lastIndex downTo 0; lastIndex — номер последнего элемента, size - 1.
Изменить элементы по номеру
В изменяемом списке элемент можно заменить через номер:
fun main() {
val prices = mutableListOf(100, 250, 80)
for (i in prices.indices) {
prices[i] = prices[i] * 2
}
println(prices)
}[200, 500, 160]Если нужен новый список, а не изменение старого, короче mapIndexed: list.mapIndexed { i, x -> x * i } возвращает новый список, исходный не меняется.
Частая ошибка: 0..list.size
fun main() {
val list = listOf(1, 2, 3)
for (i in 0..list.size) {
println(list[i])
}
}0..list.size включает и size — здесь 3, а последний номер — 2. Программа выведет три числа и упадёт с ошибкой IndexOutOfBoundsException (или ArrayIndexOutOfBoundsException). Правильно — list.indices, 0 until list.size или 0..<list.size.
Перебор for (x in list) нельзя совмещать с удалением из того же списка: при list.remove(x) внутри такого цикла программа обычно падает с ConcurrentModificationException. Удаляйте элементы по условию одной командой: list.removeAll { it < 0 } — или соберите новый список через filter.