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

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

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

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

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

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

Ниже разобраны все рабочие приёмы: прямой и обратный обход, перебор с индексом, безопасное удаление элементов, обход многомерных массивов, а также проверка результата и типичные ошибки. Примеры написаны на встроенном языке 1С и применимы как в толстом клиенте, так и в тонком и веб-клиенте.

Способ 1. Обход циклом «Для Каждого»

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

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

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

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

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

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

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

КонецЦикла;

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

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

Способ 2. Обход по индексу циклом «Для»

Когда нужна позиция элемента или возможность изменить сам элемент массива, используется классический цикл «Для» с обращением по индексу. Индексация массивов в 1С начинается с нуля, поэтому последний элемент имеет индекс «Количество() - 1».

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

МассивТоваров[Индекс] = СокрЛП(МассивТоваров[Индекс]);

КонецЦикла;

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

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

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

Способ 3. Обратный обход и безопасное удаление элементов

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

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

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

Если ПустаяСтрока(МассивТоваров[ОбратныйИндекс]) Тогда

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

КонецЕсли;

КонецЦикла;

Альтернатива — не удалять из исходного массива, а собирать новый: пройти «Для Каждого» по исходному и добавлять в новый массив только подходящие элементы. Этот вариант проще для понимания и безопаснее, но требует дополнительной памяти под вторую коллекцию. Для массивов разумного размера разница несущественна.

Когда обратный обход обязателен

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

Обход многомерных массивов

В 1С многомерный массив реализуется как массив массивов: каждый элемент внешней коллекции сам является массивом. Обход выполняется вложенными циклами, и

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

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

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

КонецЦикла;

КонецЦикла;

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

Обход с условием: фильтрация и поиск

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

Индекс = МассивТоваров.Найти("Номенклатура 2");

Если Индекс <> Неопределено Тогда

Сообщить("Найдено на позиции " + Индекс);

КонецЕсли;

Метод Найти() сравнивает значения «на равенство» и не подходит для сложных условий (например, поиск по части строки или по свойству объекта). В таких случаях нужен полный обход с проверкой условия внутри цикла. Если поиск выполняется многократно по одному и тому же набору данных, эффективнее один раз построить соответствие, где ключ — искомое значение, и обращаться к нему вместо повторных переборов.

Проверка результата и типичные ошибки

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

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

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

Сравнение вариантов обхода

Для Каждого

Чтение всех элементов без индекса. Не подходит для удаления и изменения примитивных значений

Для по индексу

Изменение элементов, работа с позицией, частичный обход. Требует аккуратности с границами

Обратный обход

Удаление элементов из того же массива. Избыточен для простого чтения

Сбор нового массива

Фильтрация без изменения исходной коллекции. Требует дополнительной памяти

FAQ

Как узнать количество элементов массива в 1С?

Методом Количество(): Массив.Количество(). Для пустого массива вернёт 0. Помните, что последний допустимый индекс — Количество() - 1, так как нумерация начинается с нуля.

Можно ли прервать обход массива досрочно?

Да, оператором «Прервать» — цикл завершится немедленно. Оператор «Продолжить» пропускает текущую итерацию и переходит к следующему элементу. Оба оператора работают и в «Для Каждого», и в «Для».

Как обойти массив в обратном порядке без удаления элементов?

Циклом «Для» с вычислением обратного индекса: Для Индекс = 0 По Массив.Количество() - 1 Цикл, а внутри обращаться к Массив[Массив.Количество() - 1 - Индекс]. Отдельного оператора обратного перебора во встроенном языке нет.

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

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

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

На типовых объёмах данных разница практически незаметна, выбирайте по удобству и безопасности кода. Реальное влияние на производительность оказывает не тип цикла, а лишние переборы: замена повторных поисков на соответствие даёт больший эффект.

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

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

Итог

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

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