Kotlin|Циклы

Циклы в Kotlin

Цикл — разновидность управляющей конструкции в высокоуровневых языках программирования, предназначенная для организации многократного исполнения набора инструкций. (Wikipedia)

Простыми словами это просто конструкции которые нам помогают исполнять многократно какие то инструкции. Например: у нас есть массив в нем оценки студентов, допустим в массиве 1000 оценок, перебирать их вручную просто не реально поэтому мы используем цикл. Без цикла нам бы пришлось написать 1000 строчек кода проверяя например с помощью условия if что нам нужно, возможно мы ищем лучшую оценку и.т.д. С помощью циклов мы можем повторить одну и туже операцию 1000 раз просто меняя номер ячейки в массиве, в таком случае у нас будет всего несколько строчек когда а не 1000.  

Для этих целей в Kotlin мы можем использовать цикл for, while и do while.

Давайте рассмотрим примеры использования цикла for. У цикла for есть разные конструкции для создания цикла, например: 

 val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
    for(fruit in fruitArray){
        //Начало цикла
        Log.d("MyLog", "Fruit: $fruit")
        // Конец цикла если цикл уже запустился
        // столько раз сколько элементов в массиве
        // если нет то запускается снова взяв
        // следующий элемент из массива
    }
    // fruit это один элемент массива который нам выдает цикл
    // цикл достает по очереди элементы из массива
    // и записывает их в переменную fruit

    // in проверяет берет элемент из массива и присваивает его переменной fruit
    // fruitArray это массив который содержит название фруктов
}

Результат будет следующий, в консоли LogCat мы увидем выход:

  • Fruit: Яблоко
  • Fruit: Апельсин
  • Fruit: Груша



В данном случае мы берем из массива с помощью цикла сразу элемент массива и мы незнаем на какой позиции данный элемент, но иногда нам нужно знать позицию элемента и нам нужен сам элемент с данной позиции, для этих случаев у  массива есть диапазон элементов внутри. Для этого просто после названия массива пишем indices, данный метод нам возвращает диапазон. Например как в нашем примере fruitArray.indices выдаст диапазон 0..2, этот диапазон принимает цикл и в таком случае будет записывать в переменную fruit не элемент из массива а его позицию. По этому мы называем теперь эту переменную например index. 

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
Log.d("MyLog", "Range: ${fruitArray.indices}")

в данном примере fruitArray.indices без цикла нам просто выдает диапазон позиций, выход в LogCat будет следующий:

  • Range: 0..2

Используя indices мы получаем позицию каждый раз когда запускается цикл и с помощью позиции мы можем получить элемент массива, надеюсь вы помните как можно получить элемент массива по позиции, таким образом у нас есть и позиция и сам элемент. Вот простой пример:

  val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
    for(index in fruitArray.indices){
        //Начало цикла
        Log.d("MyLog", "Fruit: ${fruitArray[index]} | Fruit position: $index")
        // Конец цикла если цикл уже запустился
        // столько раз сколько элементов в массиве
        // если нет то запускается снова взяв
        // следующий элемент из массива
    }
    // index позиция которую нам выдает цикл
    // цикл запускает столько раз сколько элементов в массиве
    // меняя каждый раз index на новую позицию
    // используя index берем с этой позиции
    // из массива fruitArray, элемент по его позиции
}

Выход в LogCat будет следующий:

  • Fruit: Яблоко | Fruit position: 0
  • Fruit: Апельсин | Fruit position: 1
  • Fruit: Груша | Fruit position: 2

Для этих целей есть и специальная конструкция которая сразу выдаст две переменные позицию и элемент из массива на этой позиции, для этого используем метод который есть у массива withIndex() и так как у нас теперь будет две переменные, нам нужно заключить их в скобки и написать через запятую, пример: (index, item). В первую переменную запишется позиция а во вторую элемент из массива:

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
for((index, fruit) in fruitArray.withIndex()){
Log.d("MyLog", "Fruit: $fruit | Index: $index ")
}

Результат будет следующий:

  • Fruit: Яблоко | Index: 0 
  • Fruit: Апельсин | Index: 1 
  • Fruit: Груша | Index: 2 

Если мы хотим запустить цикл определенное количество раз не используя массив мы можем сами указать диапазон таким способом:

for(index in 0..10){
    Log.d("MyLog", "Index: $index")
  }

Результат будет следующий:

  • Index: 0
  • Index: 1
  • Index: 2
  • Index: 3
  • Index: 4
  • Index: 5
  • Index: 6
  • Index: 7
  • Index: 8
  • Index: 9
  • Index: 10

цикл запустился 11 раз

А что если нам нужно запустить цикл на оборот, что бы он запускал позиции от последней к первой? Для этого у нас тоже есть ключевые слова в цикле это downTo и step. Ключевое слово downTo указывает циклу что нужно запускать позиции от большей к меньшей и впереди ключевого слова downTo пишем до какой позиции. Например downTo 3 от последней до позиции 3. Посмотрим как это выглядит в коде и результат:

for(index in 10 downTo 3){
Log.d("MyLog", "Index: $index ")
}

Результат будет следующий:

  • Index: 10 
  • Index: 9 
  • Index: 8 
  • Index: 7 
  • Index: 6 
  • Index: 5 
  • Index: 4 
  • Index: 3 

тоже самое можно сделать и с буквами:

for(letter in 'Z' downTo 'A'){
 Log.d("MyLog", "Index: $letter ")
}

Думаю вы догадались какой будет результат.

Иногда бывает так что нам нужно запустить цикл не от первой позиции а например с позиции 10 или с половины массива, в данном случае мы не можем использовать indices так как нам выдаст диапазон  0..9, в таких случаях мы можем использовать ключевое слово until. мы указываем начальную позицию ключевое слово until и после размер массива size. В таком случае нам не нужно беспокоится что мы выйдем за пределы массива.

Можно было бы и самим побеспокоится чтобы не выйти за пределы массива не используя ключевое слово until, использую диапазон и размер массива size – 1. Вот пример где выходим за пределы массива и выходит ошибка :

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
for(index in 1..fruitArray.size){
Log.d("MyLog", "Fruit: ${fruitArray[index]} ")
}

В данном примере я указал что цикл будет считать с позиции 1 а на этой позиции у нас “Апельсин” по этому когда цикл запустится то с помощью переменной index будет брать из массива элементы начиная с позиции 1 до размера массива, мы уже об этом говорили, у нас в массиве в данном случае 3 элемента это значит что размер массива это 3, вот тут и возникает проблема, цикл будет запускаться до позиции 3 включительно но у нас последняя позиция это позиция 2. Такой будет результат при запуске данного кода:

  • Fruit: Апельсин 
  • Fruit: Груша 

java.lang.ArrayIndexOutOfBoundsException: length=3; index=3

Мы вышли за пределы массива! Чтобы этого не произошло просто нужно добавить -1 к размеру массива тогда цикл будет запускать позиции как нужно и никогда не выйдет за пределы массива:

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
for(index in 1..fruitArray.size - 1){
Log.d("MyLog", "Fruit: ${fruitArray[index]} ")
}

Теперь все верно результат будет уже без ошибки:

  • Fruit: Апельсин 
  • Fruit: Груша 

Но Android Studio нас будет предупреждать что мы можем упростить данный код и убедится что цикл не выйдет за пределы массива с помощью ключевого слова until.

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
for(index in 1 until fruitArray.size){
Log.d("MyLog", "Fruit: ${fruitArray[index]} ")
}

Мы можем прервать цикл в любой момент используя ключевое слово break.

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
    for(fruit in fruitArray){
if(fruit == "Апельсин") break
 Log.d("MyLog", "Fruit: $fruit")
}
}

когда цикл дойдет до элемента “Апельсин” цикл прервется. Результат будет такой:

  • Fruit: Яблоко

Мы можем “перепрыгнуть” одну позицию и продолжить цикл со следующей позиции с помощью continue:

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
    for(fruit in fruitArray){
if(fruit == "Апельсин") continue
 Log.d("MyLog", "Fruit: $fruit")
}
}

результат будет такой:

  • Fruit: Яблоко
  • Fruit: Груша

У массивов и списков есть и встроенный цикл forEach который пройдется по всем элементам массива или списка:

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
fruitArray.forEach {
      Log.d("MyLog", "Fruit: $it")
}

В данном случае этот цикл нам будет по очереди выдавать элементы массива в виде переменной it, результат будет такой:

  • Fruit: Яблоко
  • Fruit: Апельсин
  • Fruit: Груша

В Kotlin есть еще цикл while и do while эти два цикла одинаковые разница лишь в том что do while один раз точно запустится а дальше уже зависит от условия которое напишем. Цикл while только запустится если условие верно.

Оба цикла принимают значение true или false поэтому мы можем использовать условия как в условии if. Вот пример обоих циклов:

val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
var index = 0
while (index < fruitArray.size){
Log.d("MyLog","Fruit: ${fruitArray[index]}")
index++
}

Результат будет такой: 

  • Fruit: Яблоко
  • Fruit: Апельсин
  • Fruit: Груша

Но если мы сделаем например index = 5 то цикл просто не запуститься так как условие будет выдавать false а вот do while в таком случае один раз все равно запустится но выдаст ошибку так как мы пытаемся взять с позиции 5 элемент массива а такой позиции у нас нет. Так пишется цикл do while:

 val fruitArray = listOf("Яблоко", "Апельсин", "Груша")
    var index = 0
    do {
Log.d("MyLog","Fruit: ${fruitArray[index]}")
index++
} while (index < fruitArray.size)

В данном случае ошибок нет и работает как и while, результат будет такой же:

  • Fruit: Яблоко
  • Fruit: Апельсин
  • Fruit: Груша

но в случае если index выбран больше чем размер массива один раз все равно запустится но выдаст ошибку о которой написано выше. Таким образом работают циклы, на практике будем на реальных примерах изучать как работают циклы и где их применять.

2 комментария для “Kotlin|Циклы”

Добавить комментарий

Ваш адрес email не будет опубликован. Обязательные поля помечены *