К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как перебрать массив в цикле в 1С: способы, примеры и ошибки

Как перебрать массив в цикле в 1С: Для Каждого, цикл по индексу, Количество(), ВГраница(). Примеры кода, типичные ошибки и выбор способа обхода массива.

Массив во встроенном языке 1С — одна из базовых коллекций, и обход его элементов встречается практически в любом прикладном коде: при обработке списка документов, строк табличной части, результатов запроса, выгруженных в массив. Платформа предлагает несколько способов перебора, и выбор между ними влияет не только на читаемость кода, но и на корректность логики, особенно когда внутри цикла элементы удаляются или добавляются.

Основных подхода два: цикл Для Каждого ... Из ... Цикл, который последовательно отдаёт каждый элемент, и классический цикл Для ... По ... Цикл с обращением по индексу. У каждого есть свои сценарии применения и ограничения. Ниже разобраны оба варианта с работающими примерами, способы перебора в обратном порядке, типичные ошибки и критерии выбора.

Базовый перебор циклом «Для Каждого»

Цикл Для Каждого — рекомендуемый способ, когда нужно просто обработать каждый элемент массива и позиция элемента не важна. Переменная цикла на каждой итерации получает значение очередного элемента, начиная с нулевого индекса и до конца коллекции.

МассивТоваров = Новый Массив;

МассивТоваров.Добавить("Номенклатура 1");

МассивТоваров.Добавить("Номенклатура 2");

МассивТоваров.Добавить("Номенклатура 3");

Для Каждого Товар Из МассивТоваров Цикл

Сообщить(Товар);

КонецЦикла;

Такой вариант короче, исключает ошибки с границами индексов и лучше читается. Важно понимать ограничение: переменная цикла содержит копию значения для простых типов (числа, строки, даты). Присваивание Товар = "Новое значение" внутри цикла не изменит элемент массива — изменится только локальная переменная. Если элемент — объект (например, строка таблицы значений или структура), то через переменную цикла можно менять его свойства, потому что передаётся ссылка на объект.

Перебор по индексу: Для ... По ... Цикл

Когда нужен индекс элемента, используют числовой цикл от нуля до верхней границы массива. Верхнюю границу возвращает метод ВГраница() — это индекс последнего элемента, то есть Количество() - 1.

Для Инд = 0 По МассивТоваров.ВГраница() Цикл

Сообщить("Позиция " + Инд + ": " + МассивТоваров[Инд]);

КонецЦикла;

Обращение к элементу выполняется оператором квадратных скобок: МассивТоваров[Инд]. Через индекс можно не только читать, но и изменять элемент: МассивТоваров[Инд] = НовоеЗначение; — в отличие от присваивания переменной цикла «Для Каждого», это реально меняет содержимое массива.

Частая ошибка — использовать Массив.Количество() как верхнюю границу цикла. Индексация в 1С начинается с нуля, поэтому последний допустимый индекс — Количество() - 1. Обращение Массив[Массив.Количество()] вызовет ошибку «Индекс находится за границами массива». Метод ВГраница() решает эту проблему и делает намерение кода понятнее.

1c
Для Инд = 0 По Массив.ВГраница() Цикл
    Массив[Инд] = СокрЛП(Массив[Инд]);
КонецЦикла;

Обратный перебор и удаление элементов внутри цикла

Если внутри цикла нужно удалять элементы из того же массива, прямой перебор «Для Каждого» не подходит: модификация коллекции во время её обхода приводит к пропуску элементов или ошибке. Стандартный приём — обход с конца к началу с отрицательным шагом.

Для Инд = -Массив.ВГраница() По 0 Цикл

РеальныйИндекс = -Инд;

Если Не ЗначениеЗаполнено(Массив[РеальныйИндекс]) Тогда

Массив.Удалить(РеальныйИндекс);

КонецЕсли;

КонецЦикла;

Здесь используется приём с отрицательным шагом: в 1С нет явного параметра шага, поэтому переменная цикла пробегает от -ВГраница() до 0, а реальный индекс получается сменой знака. Удаление с конца безопасно, потому что сдвигаются только индексы уже обработанных элементов.

Альтернатива — цикл Пока с ручным управлением индексом: если элемент удалён, индекс не увеличивается; если оставлен — увеличивается на единицу. Оба подхода рабочие, выбор зависит от сложности условия удаления.

Типичные ошибки
01
Удаление элементов массива внутри цикла «Для Каждого» или прямого цикла по индексу — часть элементов пропускается, логика нарушается; удаляйте при обратном обходе.
02
Использование Количество() как верхней границы вместо ВГраница() — ошибка «индекс за границами массива» на последней итерации.
03
Попытка изменить элемент массива через переменную цикла «Для Каждого» для простых типов — меняется копия, массив остаётся прежним.
04
Перебор пустого массива с обращением к элементу до проверки Количество() — обращение Массив[0] к пустому массиву вызывает ошибку.

Перебор массива с дополнительной логикой: Прервать и Продолжить

Внутри любого цикла доступны операторы управления итерациями. Прервать полностью завершает цикл — это стандартный приём для поиска первого подходящего элемента. Продолжить пропускает остаток тела цикла и переходит к следующей итерации — удобно для фильтрации элементов без вложенных условий.

НайденныйЭлемент = Неопределено;

Для Каждого Элемент Из Массив Цикл

Если Элемент = Неопределено Тогда

Продолжить;

КонецЕсли;

Если Элемент.Сумма > 100000 Тогда

НайденныйЭлемент = Элемент;

Прервать;

КонецЕсли;

КонецЦикла;

Для поиска по простому значению цикл вообще не обязателен: метод Массив.Найти(Значение) возвращает индекс первого вхождения или Неопределено. Цикл нужен, когда условие сложнее равенства — например, сравнение по свойству объекта или по диапазону.

Выбор способа перебора под задачу

Решение о том, каким циклом обходить массив, принимается по трём вопросам: нужен ли индекс, будут ли элементы изменяться по значению, будет ли массив модифицироваться (удаление/вставка) во время обхода.

Маршрут решения

Как выбрать способ обхода

Нужно только прочитать каждый элементИспользуйте «Для Каждого Элемент Из Массив Цикл» — короче и безопаснее
Нужен индекс элемента или изменение значения элементаИспользуйте «Для Инд = 0 По Массив.ВГраница() Цикл» с обращением Массив[Инд]
Внутри цикла элементы удаляютсяОбходите массив с конца через отрицательный шаг или цикл «Пока» с ручным индексом
Нужно найти элемент по точному значениюИспользуйте Массив.Найти(Значение) вместо цикла

Проверка результата и отладка обхода

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

Контрольные точки

Как проверить результат

Поведение на пустом массиве
Норма

Цикл просто не выполняется ни разу, ошибок нет

Тревожный признак

Ошибка обращения к элементу или деление на ноль внутри логики

Обработка последнего элемента
Норма

Последний элемент обрабатывается ровно один раз

Тревожный признак

Последний элемент пропущен или обрабатывается дважды — ошибка границ цикла

Удаление элементов
Норма

Удалены все и только те элементы, что соответствуют условию

Тревожный признак

Часть подходящих элементов осталась — признак прямого обхода при удалении

Для отладки удобно выводить индекс и значение через Сообщить() или использовать точку останова в конфигураторе с просмотром содержимого массива в табло. В отладчике массив раскрывается как список элементов с индексами, что позволяет быстро увидеть, на какой итерации логика отклоняется от ожидаемой.

Частые вопросы

Чем отличается ВГраница() от Количество()?

Количество() возвращает число элементов массива, а ВГраница() — индекс последнего элемента, то есть Количество() минус один. Для пустого массива ВГраница() вернёт -1, поэтому цикл «Для Инд = 0 По Массив.ВГраница()» корректно не выполнится ни разу.

Можно ли перебрать массив циклом «Пока»?

Да. Заведите переменную-счётчик Инд = 0 и пишите «Пока Инд < Массив.Количество() Цикл», увеличивая Инд внутри тела. Такой вариант удобен, когда шаг обхода зависит от условий — например, при удалении элементов индекс не увеличивается.

Как перебрать двумерный массив (массив массивов)?

Используйте вложенные циклы: внешний обходит строки, внутренний — элементы каждой строки. Например: «Для Каждого Строка Из МассивСтрок Цикл» и внутри «Для Каждого Ячейка Из Строка Цикл». Для табличных данных чаще удобнее таблица значений, чем массив массивов.

Почему изменение элемента в «Для Каждого» не срабатывает?

Переменная цикла получает копию значения для примитивных типов. Присваивание новой строки или числа этой переменной не затрагивает массив. Чтобы изменить элемент, обратитесь к нему по индексу: Массив[Инд] = НовоеЗначение.

Что быстрее: «Для Каждого» или цикл по индексу?

На типовых прикладных объёмах данных разница в производительности практически незаметна, выбирать стоит по удобству и безопасности кода. Заметный выигрыш даёт не смена вида цикла, а отказ от лишних операций внутри него — например, вызовов запросов в теле цикла.

Как проверить массив на пустоту перед перебором?

Достаточно условия «Если Массив.Количество() = 0 Тогда». Сам цикл перебора пустого массива ошибки не вызовет — он просто не выполнится, поэтому отдельная проверка нужна только если последующая логика требует хотя бы одного элемента.

Итог

Что важно запомнить

Для простого чтения элементов используйте «Для Каждого», для работы с индексами и изменения значений — цикл «Для ... По ... ВГраница()», а при удалении элементов обходите массив с конца. Проверяйте код на пустом массиве и на граничных элементах — там скрывается большинство ошибок.