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

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

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

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

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

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

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

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

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

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

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

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

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

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

КонецЦикла;

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

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

bsl
Для Каждого Элемент Из Массив Цикл
    Если Элемент = ИскомоеЗначение Тогда
        Найден = Истина;
        Прервать;
    КонецЕсли;
КонецЦикла;

Перебор по индексу через цикл «Для»

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

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

Массив[Инд] = СокрЛП(Массив[Инд]); // изменяем сам элемент

Сообщить("Элемент №" + (Инд + 1) + ": " + Массив[Инд]);

КонецЦикла;

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

Если массив может быть пустым, цикл со счётчиком просто не выполнится ни разу — отдельная проверка не обязательна, но для читаемости кода её иногда добавляют явно через Если Массив.Количество() > 0 Тогда.

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

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

Для Сч = 1 По Массив.Количество() Цикл

Инд = Массив.Количество() - Сч;

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

Массив.Удалить(Инд);

КонецЕсли;

КонецЦикла;

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

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

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

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

Для Каждого Ячейка Из Строка Цикл

Сообщить(Ячейка);

КонецЦикла;

КонецЦикла;

На практике чаще всего в массиве хранятся структуры или ссылки на объекты базы. Обращение к полям идёт через точку: Элемент.Номенклатура, Элемент.Количество. Если не все элементы гарантированно имеют одинаковый состав полей, перед обращением проверяйте наличие свойства через Элемент.Свойство("Количество", НайденноеЗначение) — иначе получите ошибку обращения к несуществующему полю.

Полезные методы массива вместо ручного перебора

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

  • Массив.Найти(Значение) — возвращает индекс первого вхождения или Неопределено, если элемента нет;
  • Массив.ВГраница() — индекс последнего элемента, равен Количество() - 1; для пустого массива вернёт -1;
  • Массив.Вставить(Индекс, Значение) и Массив.Удалить(Индекс) — модификация без ручного сдвига элементов;
  • Массив.Очистить() — удаление всех элементов одним вызовом.

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

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

Для Каждого ... Из

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

Для со счётчиком (прямой)

Нужен, когда требуется индекс или изменение элементов по месту. Требует аккуратности с границей Количество()-1.

Для со счётчиком (обратный)

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

Новый массив-результат

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

Как проверить корректность перебора

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

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

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

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

С какого индекса начинается массив в 1С?

С нуля. Первый элемент — Массив[0], последний — Массив[Массив.Количество() - 1]. Метод ВГраница() возвращает индекс последнего элемента и эквивалентен Количество() - 1.

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

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

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

Через присваивание переменной цикла — нет, изменится только локальная переменная. Но если элемент — объект (структура, ссылка), можно менять его поля через точку: Элемент.Поле = Значение. Для замены самих элементов используйте цикл с индексом.

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

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

Как найти элемент в массиве без цикла?

Методом Массив.Найти(Значение): он вернёт индекс первого совпадения или Неопределено. Метод ищет только по точному равенству; для поиска по условию (например, по полю структуры) нужен цикл с Прервать после нахождения.

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

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

Итог

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

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