Цикл for

Еще одним циклом в Kotlin является цикл for. Он позволяет обходить составные объекты, извлекая из них отдельные элементы. Если у нас есть массив, вовсе не обязательно выяснять его длину, вводить дополнительную переменную для обозначения индекса, чтобы просмотреть все элементы. С циклом for все намного проще.

fun main() {
    val a = arrayOf(2, -4, 10, 7, 4)
 
    for (i in a)
        println(i)
}

Перебор массива в цикле for в Kotlin

В заголовке цикла for нет условия. Вместо этого в круглых скобках используется особая синтаксическая конструкция. Ключевое слово in здесь обозначает не проверку вхождения того, что слева, в то, что справа. Слева находится переменная, которой в порядке очередности на каждом новом витке (итерации) цикла присваивается очередной элемент, содержащийся в объекте справа.

В примере выше на первой итерации цикла переменная i связывается с числом 2, на второй – с числом -4 и т. д. Когда элементы массива заканчиваются, цикл прекращает свою работу.

Допустим, требуется изменить все элементы массива. Чтобы перезаписать их, надо перебирать индексы массива, а не сами элементы. Ведь само по себе извлеченное значение никакой информации о своем индексе не содержит. Чтобы перебирать индексы, надо знать длину массива, то есть его размер. А поскольку индексация начинается с нуля, перебирать надо числа от нуля до размер массива минус единица.

fun main() {
    val a = arrayOf(2, -4, 10, 7, 4)
    val s = a.size1
 
    for (i in 0..s) {
        a[i] /= 2
        println(a[i])
    }
}

Использование диапазонов в цикле for в Kotlin

Переменная s равна четырем, поэтому выражение 0..s преобразуется в 0..4. Такое выражение в Kotlin создает особый объект – диапазон. Его элементами являются числа от начальной границы до конечной включительно. В данном случае это будут числа 0, 1, 2, 3, 4, что как раз соответствует индексам элементов массива.

В теле цикла мы делим каждый элемент на 2. Выражение a[i] /= 2 – это сокращенная запись a[i] = a[i] / 2, когда мы берем из массива элемент по его индексу, делим на 2, результат присваиваем той же ячейке массива.

При выводе элемента на экран следует не забывать, что i – это теперь индекс, а не сам элемент. Чтобы получить значение элемента, его надо извлечь выражением a[i].

Обратите внимание, в данном случае цикл for обходит вовсе не элементы массива, а диапазон 0..s.

В Kotlin есть и другие способы получить индексы массива. Например, свойство indeces, которое сразу возвращает нужный диапазон.

fun main() {
    val a = arrayOf(2, -4, 10, 7, 4)
    val s = a.indices
 
    for (i in s) {
        a[i] /= 2
        println(a[i])
    }
}

От переменной s можно избавиться, перенеся выражение a.indices сразу в заголовок for:

fun main() {
    val a = arrayOf(2, -4, 10, 7, 4)
 
    for (i in a.indices) {
        a[i] /= 2
        println(a[i])
    }
}

Поскольку строки в определенном смысле можно рассматривать как массивы символов (на самом деле это не так, так как строки неизменяемые – символы в них изменять нельзя), мы можем использовать цикл for и для перебора символов строки:

fun main() {
    val s = readLine()!!
 
    for (char in s) {
        println(char + "!")
    }
    println()
 
    for (i in s.indices.reversed()) {
        print(s[i])
    }
}

Перебор символов строки с помощью цикла for

Извлекать символы строки можно по индексу, а вот перезаписать, например, выражением s[i] = 'a', нельзя. Обратите внимание, мы не создаем массив строк. Здесь мы рассматриваем одну строку как "массив" символов.

Выражение s.indices.reversed() сначала создает диапазон от 0 до длины строки, а затем его переворачивает. Например, был диапазон 0..2, станет 2..0. Однако такие обратные диапазоны в языке программирования Kotlin определяются через слово downTo, а не две точки:

val d = 10 downTo 5

Практическая работа:

  1. Заполните массив с помощью цикла for случайными числами в диапазоне от -10 до 10. Выведите элементы на экран. С помощью другого цикла for замените отрицательные значения массива на 0. Снова выведите элементы на экран.

  2. Создайте массив строк. Выведите на экран только те строки, которые содержат определенный символ.