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