Удаляйте элементы с конца
страницаУдаляйте элементы с конца
И вот последний, четвертый, «секрет». Инструкция Для Каждого Цикл очень удобная и простая. Так и хочется ею пользоваться! Но тут главное – не переусердствовать. Потому что бывают задачи, когда элементы коллекции обязательно нужно перебирать в определенном порядке. Хотя, на первый взгляд, в этом нет никакой необходимости.
Чтобы все увидеть своими глазами, сделайте простой пример (листинг 7.16).
Листинг 7.1****6. Удалить все числа, которые меньше 10. Неправильный вариант
Числа = Новый Массив();
Числа.Добавить(10);
Числа.Добавить(8);
Числа.Добавить(4);
Числа.Добавить(15);
Для Каждого ТекущееЧисло Из Числа Цикл
Если ТекущееЧисло < 10 Тогда
Числа.Удалить(Числа.Найти(ТекущееЧисло));
КонецЕсли;
КонецЦикла;
Задача очень простая. У вас есть массив из четырех чисел. Вам нужно удалить из этого массива все числа, которые меньше 10.
Поставьте точку останова на инструкции Если и запустите проект в режиме отладки.
Не ожидая подвоха, вы написали Для Каждого Цикл, и дальше происходит вот что. На первой итерации цикла ТекущееЧисло у вас – 10 (рис. 7.180).

Рис. 7.1****80. Первая итерация цикла
На второй итерации цикла ТекущееЧисло у вас будет 8 (рис. 7.181).

Рис. 7.18****1. Вторая итерация цикла
И тут вы обнаруживаете, что этот элемент нужно удалить. Коллекции не терпят пустых мест. Как только вы его удаляете, остальные элементы коллекции перемещаются, чтобы занять освободившееся место (рис. 7.182).

Рис. 7.18****2. После удаления элемента 8
Получается, что на втором месте оказалось число 4, которое вы еще не обрабатывали. Но цикл продолжается, и на третьей итерации вы, естественно, переходите к следующему элементу коллекции (рис. 7.183).

Рис. 7.18****3. Третья итерация цикла
Теперь ваше текущее число 15. А 4 «проскочила» мимо вас. И осталась в массиве.
Если вспомнить, что вы представляли массив как стеллаж, то, когда вы удаляете один из мячиков, все остальные, которые находятся выше него, «проваливаются» вниз (рис. 7.184).

Рис. 7.18****4. Остальные мячики проваливаются вниз
И мячик, который вы должны были бы обработать на следующем шаге, проскакивает мимо вас.
Чтобы такого не случалось, нужно двигаться сверху вниз, то есть от конца к началу (рис. 7.185).

Рис. 7.18****5. Обход массива с конца
Тогда, если вы удалите элемент 4, вниз «провалится» элемент с той полки, которую вы уже обрабатывали, – 15. И это не страшно.
Как все то же самое сделать на встроенном языке? Довольно просто. Но для этого нужно будет использовать еще один вид инструкции цикла – Пока Цикл (листинг 7.17).
Листинг 7.1****7. Удалить все числа, которые меньше 10. Правильный вариант
ТекущийИндекс = Числа.ВГраница();
Пока ТекущийИндекс >= 0 Цикл
Если Числа[ТекущийИндекс] < 10 Тогда
Числа.Удалить(ТекущийИндекс);
КонецЕсли;
ТекущийИндекс = ТекущийИндекс - 1;
КонецЦикла;
В такой форме записи цикл выполняется до тех пор, пока выражение, записанное между Пока и Цикл, равно Истина. Как только это выражение становится равно Ложь, выполнение цикла прекращается.
Чтобы обходить цикл, вы создаете переменную ТекущийИндекс. В ней будет находиться индекс того элемента массива, который нужно обработать. Сначала вы помещаете в эту переменную индекс последнего элемента (листинг 7.18).
Листинг 7.1****8. Помещаете индекс самого последнего элемента
ТекущийИндекс = Числа.ВГраница();
В конце тела цикла вы каждый раз уменьшаете этот индекс на единицу. Это позволяет вам двигаться от конца к началу (листинг 7.19).
Листинг 7.1****9. Уменьшаете индекс на единицу
ТекущийИндекс = ТекущийИндекс – 1;
А в условии цикла вы проверяете, не стал ли текущий индекс отрицательным. Как только он становится меньше нуля, исполнение цикла завершается (листинг 7.20).
Листинг **7.**20. Проверяете, не стал ли текущий индекс отрицательным
Пока ТекущийИндекс >= 0 Цикл
Таким образом вы обходите все индексы от последнего к нулевому. Сделайте этот пример в своей конфигурации. Пройдите его в режиме отладки по шагам, посмотрите, как он работает. Убедитесь, что в результате в массиве останутся только два значения: 10 и 15.