Работая с данными, в какой-то момент понимаешь, что не всё можно представить в виде линейной информации.
Например, если мы говорим о текстах, то это обычные строки JavaScript. Что я имею ввиду? Смысл строк в том, что есть какой-то символ(или символы) и есть какая-то определённая последовательность этих символов. По сути, это выглядит как линия с «началом» и «концом» и чётким равномерным «шагом«. Если сравнивать это с пространством, то это одномерное пространство в котором есть только ось ИКС.
function get1for(){
let a = 0;
for(q1 = 0; q1 < 10; q1++){
a = a + 1
}
return a;
};
Наша функция get1for() замыкает в себе переменную «a» и в одном цикле перебирает варианты от 0 до 9 с шагом 1. Каждый перебор — каждый шаг цикла — увеличивает значение в переменной «a» на единицу. В результате мы получаем из функции число 10.
Внутри цикла мы работаем с одной переменной, которую назвали «q1«. Её увеличение с шагом цикла движется по одной оси.
Сейчас, фактически, в переменных «a» и «q1» движение идёт на одних и тех же позициях — по одной оси одномерного пространства.
Зачем нужно вкладывать один цикл в другой цикл в JavaSvript?
И вот однажды возникает потребность работать с двумерными пространствами. Они хорошо всем знакомы. Я говорю о любых картинках или изображениях. Все они имеют две оси представления информации — ширину и высоту. Эти оси можете называть как вам удобно, например ИКС и ИГРЕК.
Совокупность цветов на плоскости даёт нам зрительную информацию. Одна единица данных для нас здесь — это пиксель.
Если мы получим просто одну линию из пикселей, то мы не сможем извлечь из такого изображения ничего полезного.
Только располагая пиксели перпендикулярно друг от друга можно получить полезную информацию из плоскостного рисунка. Для понимания того, что нарисовано на изображении, наши пиксели должны располагать, как горизонтально, так и вертикально. Это называется двумерным пространством.
Чтобы обойти такое пространство пикселей, нужно иметь информацию не только текущего положения по оси ИКС, но и учитывать положение пикселя по оси ИГРЕК.
Вот для этой цели и нужно впервые использовать цикл в цикле в языке JavaScript.
function get2for(){
let a = 0;
for(q1 = 0; q1 < 10; q1++){
for(q2 = 0; q2 < 10; q2++){
a = a + 1
}
}
return a;
};
Мы вкладываем цикл в цикл и на самом глубоком уровне вложенности увеличиваем значение всё той же переменной «a» на единицу. Как думаете, что мы получим из функции?
Правильный ответ — число 100. Почему так получилось?
Пока вложенный цикл перебирает все варианты и выполняет действия, его родительский цикл ждёт завершения всех шагов своего ребёнка.
Когда значение переменной в «q1» равно 0, тогда вложенный цикл начинает перебирать свои собственные значения для переменной «q2«: 0, 1, 2, 3, 4, 5, 6, 7, 8, 9.
Как только значение в «q2» дойдёт до числа 10, то в этот момент проверка условия «q2 < 10» даст ЛОЖЬ и вложенный цикл прекратит свою работу и передаст управление родительскому циклу. В родительском цикле переменная «q1» изменит своё значение на 1 и вызовет работу вложенного цикла снова.
В результате мы просто перебираем все возможные варианты координат для двумерного пространства.
В этом примере мы как-бы работаем с картинкой размером 10 на 10 пикселей. И всего у нас получается 100 уникальных координатных значений для каждого из них.
Какая глубина вложенности циклов друг в друга может быть в JavaScript?
Правильный ответ — любая. Циклы можно вкладывать друг в друга большое количество раз. Это зависит от конкретной задачи и предметной области.
Например, можно шагнуть на ещё один уровень пространства и создать функцию по обходу трёхмерного пространства.
function get3for(){
let a = 0;
for(q1 = 0; q1 < 10; q1++){
for(q2 = 0; q2 < 10; q2++){
for(q3 = 0; q3 < 10; q3++){
a = a + 1
}
}
}
return a;
};
В ответ мы получим число 1000. Ровно столько нужно точек в пространстве, чтобы построить куб размером ребра 10.
Результат работы функции get3for():
Итог
В данной публикации рассмотрен самый простой вариант использования вложенности циклов в JavaScript. Разумеется, реальные задачи будут требовать от циклов более сложных условий. Важно понимать суть и возможности циклов при работе с ними.
Вкладывать циклы друг в друга нужно в задачах подсчётов перестановок различных генераторов. Это важный этап перед началом каких-то действий. Прежде чем сложно обрабатывать каждый отдельный случай, нужно заранее подсчитать количество этих самых случаев. Время ценно.
Задачи машинного обучения также требуют большого количества обходов разных структур данных. Без циклов эти задачи не решить.
Информационные ссылки
JavaScript | Как перевернуть массив из массивов на 90 градусов?
Стандарт ECMAScript — https://tc39.es/ecma262/multipage/
Стандарт ECMAScript — Раздел «The for Statement» — https://tc39.es/ecma262/multipage/ecmascript-language-statements-and-declarations.html#sec-for-statement