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

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

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

Как обойти массив в цикле в 1С: Для Каждого, Для По Цикл, обход в обратном порядке, вложенные массивы, типичные ошибки и примеры кода на встроенном языке.

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

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

Цикл «Для Каждого» — основной способ перебора

Конструкция Для Каждого Элемент Из Массив Цикл ... КонецЦикла последовательно помещает в переменную каждый элемент массива, начиная с нулевого и заканчивая последним. Это самый читаемый вариант, когда индекс элемента не нужен.

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

Товары.Добавить("Ноутбук");

Товары.Добавить("Монитор");

Товары.Добавить("Клавиатура");

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

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

КонецЦикла;

Переменная цикла (в примере — Товар) объявлять заранее не обязательно: она создаётся автоматически при входе в цикл. Тип значения в ней соответствует типу элемента массива, а поскольку массив в 1С может хранить значения разных типов, перед операциями вроде арифметики или сравнения строк полезно проверять тип через ТипЗнч().

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

Обход по индексу через «Для ... По ... Цикл»

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

Для Инд = 0 По Товары.Количество() - 1 Цикл

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

КонецЦикла;

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

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

Обход массива в обратном порядке и удаление элементов

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

Для Инд = -Товары.Количество() + 1 По 0 Цикл

ТекущийИндекс = -Инд;

Если Товары[ТекущийИндекс] = "Монитор" Тогда

Товары.Удалить(ТекущийИндекс);

КонецЕсли;

КонецЦикла;

Трюк с отрицательной переменной цикла — стандартный приём, поскольку шаг -1 в конструкции Для ... По ... напрямую не задаётся. Альтернатива — использовать цикл Пока с ручным уменьшением счётчика:

Инд = Товары.Количество() - 1;

Пока Инд >= 0 Цикл

Если Товары[Инд] = "Монитор" Тогда

Товары.Удалить(Инд);

КонецЕсли;

Инд = Инд - 1;

КонецЦикла;

Безопасное удаление из массива в цикле
  1. 1
    Определите условие удаления элемента
  2. 2
    Организуйте обход с последнего индекса к нулевому
  3. 3
    Внутри цикла проверяйте условие и вызывайте Массив.Удалить(Индекс)
  4. 4
    После цикла проверьте Массив.Количество() — оно должно уменьшиться на число удалённых

Обход вложенных массивов и массивов структур

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

// Массив структур

Для Каждого Строка Из СписокДокументов Цикл

Сообщить("Документ: " + Строка.Номер + ", сумма: " + Строка.Сумма);

КонецЦикла;

// Массив массивов

Для Каждого ВнутреннийМассив Из Матрица Цикл

Для Каждого Значение Из ВнутреннийМассив Цикл

Сообщить(Значение);

КонецЦикла;

КонецЦикла;

При обходе массива структур обращение к несуществующему ключу вызовет ошибку. Если структуры формируются в разных местах и набор ключей может отличаться, проверяйте наличие свойства через Структура.Свойство("Сумма", НайденноеЗначение) перед использованием.

Сравнение способов обхода

Выбор конструкции зависит от задачи. Сводная таблица помогает быстро определить подходящий вариант:

СпособКогда применятьОграничения
Для Каждого ... ИзПростой перебор всех элементов, чтение данныхНет индекса, нельзя изменять коллекцию в цикле
Для 0 По Количество()-1Нужен индекс, запись в элементы, доступ к соседямТребует аккуратности с границами
Обратный обход (Пока или Для с минусом)Удаление элементов, обработка с концаБолее громоздкий синтаксис
Пока с ручным счётчикомНестандартный шаг, сложные условия выходаЛегко забыть инкремент и получить бесконечный цикл

Сравнение вариантов

Для Каждого

Подходит для 90% задач чтения данных. Короткий и безопасный, но не даёт индекс и запрещает изменение коллекции.

Индексный цикл Для...По

Нужен при записи в элементы и доступе к позиции. Требует контроля границ массива.

Цикл Пока

Гибкий вариант для обратного обхода и нестандартных шагов, но проще допустить бесконечный цикл.

Типичные ошибки при обходе массива

Большинство проблем при работе с массивами сводится к нескольким повторяющимся сценариям. Знание их заранее экономит время отладки.

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

Третья частая проблема — попытка изменить элемент через переменную цикла Для Каждого. Код Элемент = НовоеЗначение внутри такого цикла не меняет содержимое массива: переменная лишь копирует ссылку на значение, а присваивание заменяет содержимое самой переменной. Для изменения используйте индексный доступ.

Типичные ошибки
01
Верхняя граница Массив.Количество() вместо Количество()-1 — ошибка «Индекс за границами массива»
02
Удаление элементов при прямом обходе — пропуск элементов из-за сдвига индексов
03
Присваивание переменной цикла Для Каждого в попытке изменить элемент — массив остаётся без изменений
04
Обращение к элементу без проверки, что массив не пуст
05
Забытый Инд = Инд + 1 в цикле Пока — зависание сеанса из-за бесконечного цикла

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

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

Полезная проверка — сравнить число итераций с Массив.Количество(). Если после цикла счётчик обработанных элементов не совпадает с размером массива, значит где-то сработал Прервать, Продолжить или коллекция менялась во время обхода.

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

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

Число итераций цикла
Норма

Равно Массив.Количество() при полном обходе

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

Меньше — сработал Прервать или коллекция изменялась

Границы индексов
Норма

Индекс от 0 до Количество()-1

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

Обращение по индексу Количество() — ошибка выполнения

Изменение элементов
Норма

Значения в массиве обновились после цикла

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

Массив не изменился — правили переменную цикла, а не элемент

FAQ

Можно ли в цикле Для Каждого узнать индекс текущего элемента?

Напрямую — нет, конструкция не предоставляет индекс. Обходной путь — завести отдельную переменную-счётчик перед циклом и увеличивать её на единицу внутри тела. Если индекс нужен постоянно, проще сразу использовать цикл Для 0 По Количество()-1.

Что будет, если обойти пустой массив?

Ничего страшного: цикл Для Каждого просто не выполнится ни разу, а индексный цикл с границей Количество()-1 получит верхнюю границу -1 и также не начнётся. Отдельная проверка на пустоту перед циклом не обязательна, но полезна, если после обхода логика зависит от наличия данных.

Как досрочно выйти из цикла или пропустить элемент?

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

Можно ли обходить массив на клиенте в управляемой форме?

Да, все описанные конструкции работают и в клиентском, и в серверном контексте. Ограничение касается не циклов, а самих данных: если массив содержит объекты, недоступные на клиенте (например, ссылки на запросы или объекты СУБД), обращение к ним вызовет ошибку контекста.

Чем массив отличается от списка значений при обходе?

Массив даёт доступ по индексу и хранит просто значения, а СписокЗначений хранит элементы с представлением, пометкой и картинкой. Цикл Для Каждого работает с обоими, но для списка значений обращение по индексу даст объект элемента списка, а не само значение — его нужно получать через свойство Значение.

Итог

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

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