Разработка и Конфигурация · 9 мин
Как перебрать массив в цикле в 1С: способы, примеры и ошибки
Как перебрать массив в цикле в 1С: Для Каждого, цикл по индексу, Количество(), ВГраница(). Примеры кода, типичные ошибки и выбор способа обхода массива.
Массив во встроенном языке 1С — одна из базовых коллекций, и обход его элементов встречается практически в любом прикладном коде: при обработке списка документов, строк табличной части, результатов запроса, выгруженных в массив. Платформа предлагает несколько способов перебора, и выбор между ними влияет не только на читаемость кода, но и на корректность логики, особенно когда внутри цикла элементы удаляются или добавляются.
Основных подхода два: цикл Для Каждого ... Из ... Цикл, который последовательно отдаёт каждый элемент, и классический цикл Для ... По ... Цикл с обращением по индексу. У каждого есть свои сценарии применения и ограничения. Ниже разобраны оба варианта с работающими примерами, способы перебора в обратном порядке, типичные ошибки и критерии выбора.
Базовый перебор циклом «Для Каждого»
Цикл Для Каждого — рекомендуемый способ, когда нужно просто обработать каждый элемент массива и позиция элемента не важна. Переменная цикла на каждой итерации получает значение очередного элемента, начиная с нулевого индекса и до конца коллекции.
МассивТоваров = Новый Массив;
МассивТоваров.Добавить("Номенклатура 1");
МассивТоваров.Добавить("Номенклатура 2");
МассивТоваров.Добавить("Номенклатура 3");
Для Каждого Товар Из МассивТоваров Цикл
Сообщить(Товар);
КонецЦикла;
Такой вариант короче, исключает ошибки с границами индексов и лучше читается. Важно понимать ограничение: переменная цикла содержит копию значения для простых типов (числа, строки, даты). Присваивание Товар = "Новое значение" внутри цикла не изменит элемент массива — изменится только локальная переменная. Если элемент — объект (например, строка таблицы значений или структура), то через переменную цикла можно менять его свойства, потому что передаётся ссылка на объект.
Перебор по индексу: Для ... По ... Цикл
Когда нужен индекс элемента, используют числовой цикл от нуля до верхней границы массива. Верхнюю границу возвращает метод ВГраница() — это индекс последнего элемента, то есть Количество() - 1.
Для Инд = 0 По МассивТоваров.ВГраница() Цикл
Сообщить("Позиция " + Инд + ": " + МассивТоваров[Инд]);
КонецЦикла;
Обращение к элементу выполняется оператором квадратных скобок: МассивТоваров[Инд]. Через индекс можно не только читать, но и изменять элемент: МассивТоваров[Инд] = НовоеЗначение; — в отличие от присваивания переменной цикла «Для Каждого», это реально меняет содержимое массива.
Частая ошибка — использовать Массив.Количество() как верхнюю границу цикла. Индексация в 1С начинается с нуля, поэтому последний допустимый индекс — Количество() - 1. Обращение Массив[Массив.Количество()] вызовет ошибку «Индекс находится за границами массива». Метод ВГраница() решает эту проблему и делает намерение кода понятнее.
Для Инд = 0 По Массив.ВГраница() Цикл
Массив[Инд] = СокрЛП(Массив[Инд]);
КонецЦикла;Обратный перебор и удаление элементов внутри цикла
Если внутри цикла нужно удалять элементы из того же массива, прямой перебор «Для Каждого» не подходит: модификация коллекции во время её обхода приводит к пропуску элементов или ошибке. Стандартный приём — обход с конца к началу с отрицательным шагом.
Для Инд = -Массив.ВГраница() По 0 Цикл
РеальныйИндекс = -Инд;
Если Не ЗначениеЗаполнено(Массив[РеальныйИндекс]) Тогда
Массив.Удалить(РеальныйИндекс);
КонецЕсли;
КонецЦикла;
Здесь используется приём с отрицательным шагом: в 1С нет явного параметра шага, поэтому переменная цикла пробегает от -ВГраница() до 0, а реальный индекс получается сменой знака. Удаление с конца безопасно, потому что сдвигаются только индексы уже обработанных элементов.
Альтернатива — цикл Пока с ручным управлением индексом: если элемент удалён, индекс не увеличивается; если оставлен — увеличивается на единицу. Оба подхода рабочие, выбор зависит от сложности условия удаления.
Перебор массива с дополнительной логикой: Прервать и Продолжить
Внутри любого цикла доступны операторы управления итерациями. Прервать полностью завершает цикл — это стандартный приём для поиска первого подходящего элемента. Продолжить пропускает остаток тела цикла и переходит к следующей итерации — удобно для фильтрации элементов без вложенных условий.
НайденныйЭлемент = Неопределено;
Для Каждого Элемент Из Массив Цикл
Если Элемент = Неопределено Тогда
Продолжить;
КонецЕсли;
Если Элемент.Сумма > 100000 Тогда
НайденныйЭлемент = Элемент;
Прервать;
КонецЕсли;
КонецЦикла;
Для поиска по простому значению цикл вообще не обязателен: метод Массив.Найти(Значение) возвращает индекс первого вхождения или Неопределено. Цикл нужен, когда условие сложнее равенства — например, сравнение по свойству объекта или по диапазону.
Выбор способа перебора под задачу
Решение о том, каким циклом обходить массив, принимается по трём вопросам: нужен ли индекс, будут ли элементы изменяться по значению, будет ли массив модифицироваться (удаление/вставка) во время обхода.
Как выбрать способ обхода
Проверка результата и отладка обхода
После написания цикла полезно проверить его поведение на граничных случаях: пустой массив, массив из одного элемента, массив, где обработке подлежат первый и последний элементы одновременно. Именно на границах чаще всего всплывают ошибки индексации.
Как проверить результат
Цикл просто не выполняется ни разу, ошибок нет
Ошибка обращения к элементу или деление на ноль внутри логики
Последний элемент обрабатывается ровно один раз
Последний элемент пропущен или обрабатывается дважды — ошибка границ цикла
Удалены все и только те элементы, что соответствуют условию
Часть подходящих элементов осталась — признак прямого обхода при удалении
Для отладки удобно выводить индекс и значение через Сообщить() или использовать точку останова в конфигураторе с просмотром содержимого массива в табло. В отладчике массив раскрывается как список элементов с индексами, что позволяет быстро увидеть, на какой итерации логика отклоняется от ожидаемой.
Частые вопросы
Чем отличается ВГраница() от Количество()?
Количество() возвращает число элементов массива, а ВГраница() — индекс последнего элемента, то есть Количество() минус один. Для пустого массива ВГраница() вернёт -1, поэтому цикл «Для Инд = 0 По Массив.ВГраница()» корректно не выполнится ни разу.
Можно ли перебрать массив циклом «Пока»?
Да. Заведите переменную-счётчик Инд = 0 и пишите «Пока Инд < Массив.Количество() Цикл», увеличивая Инд внутри тела. Такой вариант удобен, когда шаг обхода зависит от условий — например, при удалении элементов индекс не увеличивается.
Как перебрать двумерный массив (массив массивов)?
Используйте вложенные циклы: внешний обходит строки, внутренний — элементы каждой строки. Например: «Для Каждого Строка Из МассивСтрок Цикл» и внутри «Для Каждого Ячейка Из Строка Цикл». Для табличных данных чаще удобнее таблица значений, чем массив массивов.
Почему изменение элемента в «Для Каждого» не срабатывает?
Переменная цикла получает копию значения для примитивных типов. Присваивание новой строки или числа этой переменной не затрагивает массив. Чтобы изменить элемент, обратитесь к нему по индексу: Массив[Инд] = НовоеЗначение.
Что быстрее: «Для Каждого» или цикл по индексу?
На типовых прикладных объёмах данных разница в производительности практически незаметна, выбирать стоит по удобству и безопасности кода. Заметный выигрыш даёт не смена вида цикла, а отказ от лишних операций внутри него — например, вызовов запросов в теле цикла.
Как проверить массив на пустоту перед перебором?
Достаточно условия «Если Массив.Количество() = 0 Тогда». Сам цикл перебора пустого массива ошибки не вызовет — он просто не выполнится, поэтому отдельная проверка нужна только если последующая логика требует хотя бы одного элемента.
Что важно запомнить
Для простого чтения элементов используйте «Для Каждого», для работы с индексами и изменения значений — цикл «Для ... По ... ВГраница()», а при удалении элементов обходите массив с конца. Проверяйте код на пустом массиве и на граничных элементах — там скрывается большинство ошибок.