В одном из предыдущих уроков мы уже рассмотрели циклы while. Мы также изучили интервалы. Пришло время взглянуть на особенности цикла for в Kotlin. Вероятно, это самый распространенный вид циклов. Вы будете использовать его довольно часто.
Содержание статьи
Синтаксис цикла for в Kotlin
Цикл for
создается следующим образом:
1 2 3 | for (<CONSTANT> in <RANGE>) { <LOOP CODE> } |
Цикл начинается с ключевого слова for
, за которым следует название константы цикла (скоро мы поговорим и о ней), по середине у нас слово in
и сам интервал цикла через которого мы пройдемся. Далее представлен пример:
1 2 3 4 5 6 7 8 9 10 | fun main() { val count = 10 var sum = 0 for (i in 1..count) { sum += i } print(sum) } |
В приведенном выше коде, цикл for
проходит через интервал от 1
до count
. На первой итерации i
будет равняться первому элементу интервала: 1
. Каждый раз, проходя по циклу циклу, переменная i
будет увеличиваться до тех пор, пока не сравняется с count
. Цикл выполнится в последний раз, а затем завершится.
На заметку: Если вы использовали полуоткрытый интервал until, последней итерацией переменной
i
будетcount - 1
.
Внутри цикла, значение из i
добавляется к переменной sum
. Он запускается 10 раз для вычисления последовательности 1 + 2 + 3 + 4 + 5 + ...
до 10.
Далее представлены значения i
и переменной sum
для каждой итерации:
- Начало итерации 1:
i
= 1,sum
= 0 - Начало итерации 2:
i
= 2,sum
= 1 - Начало итерации 3:
i
= 3,sum
= 3 - Начало итерации 4:
i
= 4,sum
= 6 - Начало итерации 5:
i
= 5,sum
= 10 - Начало итерации 6:
i
= 6,sum
= 15 - Начало итерации 7:
i
= 7,sum
= 21 - Начало итерации 8:
i
= 8,sum
= 28 - Начало итерации 9:
i
= 9,sum
= 36 - Начало итерации 10:
i
= 9,sum
= 45 - После итерации 10:
sum
= 55
Говоря об области видимости, константа i
видна только внутри области видимости цикла for, а это значит, что она недоступна за пределами цикла.
На заметку: Если вы разбираетесь в математике, вы могли заметить, что в этом примере вычисляются треугольные числа.
Иногда требуется пройтись по циклу только определенное количество раз, и константа цикла не нужна вообще. В данном случае цикл repeat используется следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 | fun main() { var sum = 1 var lastSum = 0 repeat(10) { val temp = sum sum += lastSum lastSum = temp } print(lastSum) } |
В интервале можно указать шаг. К примеру, подсчитать сумму нечетных чисел:
1 2 3 4 5 6 7 8 9 10 | fun main() { var sum = 0 val count = 10 for (i in 1..count step 2) { sum += i } print(sum) } |
Здесь внутри цикла for есть оператор step
. Цикл будет выполняться только для значений, на которые выпадает данный шаг. В этом случае вместо того, чтобы проходить через каждое значение в интервале, цикл будет проходить через все остальные значения. Таким образом, i
всегда будет нечетным, потому что начальное значение равно 1
.
В цикле for также можно использовать обратный отсчет, используя downTo
. В таком случае, если count
имеет значение 10, цикл будет перебирать значения (10, 8, 6, 4, 2)
.
1 2 3 4 5 6 7 8 9 10 | fun main() { var sum = 0 val count = 10 for (i in count downTo 1 step 2) { sum += i } print(sum) } |
Маркированные операторы continue и break
Иногда требуется пропустить итерацию цикла для отдельного случая, не прерывая его полностью. Это можно сделать с помощью оператора continue
, который сразу завершает текущую итерацию цикла и запускает следующую. Оператор continue
дает более высокий уровень контроля, позволяя решать, где и когда пропустить итерацию.
Возьмем пример сетки 8 на 8, где каждая ячейка содержит значение строки, умноженное на столбец. Это очень похоже на таблицу умножения, не так ли?
Предположим, нужно посчитать сумму всех клеток, кроме нечетных рядов, как показано ниже:
Через цикл for это делается следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 | fun main() { var sum = 0 for (row in 0 until 8) { if (row % 2 == 0) { continue } for (column in 0 until 8) { sum += row * column } } print("Результат: $sum") } |
Строка четная если результат деления номера строки на 2 равен 0. В этом случае continue
заставляет цикл for переходить к следующей строке.
Оператор break, который мы уже использовали при изучении цикла while
, можно использовать с циклами for
и его использование прерывает работу цикла полностью. Как и break
, continue
работает как с циклами for
, так и с циклами while
.
Во втором примере кода, будет вычислена сумма всех ячеек, за исключением тех, в которых столбец больше или равен строке.
Должны складываться следующие ячейки:
С помощью цикла for
это можно сделать следующим образом:
1 2 3 4 5 6 7 8 9 10 11 12 13 | fun main() { var sum = 0 rowLoop@ for (row in 0 until 8) { columnLoop@ for (column in 0 until 8) { if (row == column) { continue@rowLoop } sum += row * column } } print("Результат: $sum") } |
Предыдущий блок кода использует маркер, помечая два цикла как rowLoop
и columnLoop
соответственно. Когда строка равна столбцу внутри цикла columnLoop
, внешний цикл rowLoop
будет продолжен.
Можно использовать такие маркированные операторы с break
, чтобы выйти из определенного цикла. Обычно break
и continue
применяются в цикле внутри цикла. Поэтому маркированные операторы нужно использовать, когда требуется манипулировать главным циклом в теле которого мы находимся.
Задания для проверки
1. Создайте константу range
, ее интервал будет от 1 до 10 включительно. Напишите цикл for
, который выполняет итерацию по этому интервалу и выводит квадрат каждого числа;
2. Напишите цикл for
для итерации того же интервала, что и в приведенном выше задании, и выведите квадратный корень из каждого числа.
3. Выше вы видели цикл for
, который перебирает только четные строки из сетки, например:
1 2 3 4 5 6 7 8 9 10 11 12 | fun main() { var sum = 0 for (row in 0 until 8) { if (row % 2 == 0) { continue } for (column in 0 until 8) { sum += row * column } } } |
Измените код, чтобы он использовал шаг step
с первым циклом for
, чтобы пропускать четные строки вместо использования continue
. Убедитесь, что сумма равна 448 как в изначальном примере.
Что значит rowLoop@? Ещё не встречал символа @.