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

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

Как работать с массивами в 1С

Практическое руководство по работе с массивами в 1С: создание, добавление и удаление элементов, обход в цикле, поиск, сортировка и типичные ошибки разработчиков.

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

Главная особенность массива в платформе 1С — он передаётся в процедуры и функции по значению, то есть при передаче создаётся копия. Это отличает его от большинства других коллекций и часто становится причиной как логических ошибок, так и лишнего расхода памяти на больших объёмах данных.

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

Создание массива и добавление элементов

Массив создаётся конструктором Новый Массив. Без параметров получится пустой массив, а если передать число — массив заданной длины, заполненный значениями Неопределено. Второй вариант полезен, когда количество элементов известно заранее и вы будете заполнять их по индексу, а не добавлять.

// Пустой массив

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

// Массив на 10 элементов, все равны Неопределено

Остатки = Новый Массив(10);

// Добавление элементов в конец

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

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

// Вставка в конкретную позицию (остальные элементы сдвигаются)

Товары.Вставить(0, "Первый элемент");

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

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

Обход массива: Для Каждого или цикл по индексу

Существует два основных способа перебрать элементы. Цикл Для Каждого ... Из ... Цикл проходит по значениям и читается проще, но не даёт доступа к индексу. Цикл со счётчиком от 0 до Количество() - 1 нужен, когда важна позиция элемента или требуется модифицировать массив по ходу обхода.

// Обход по значениям

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

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

КонецЦикла;

// Обход по индексу

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

Товары[Инд] = СокрЛП(Товары[Инд]);

КонецЦикла;

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

// Безопасное удаление в цикле — идём с конца

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

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

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

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

КонецЕсли;

КонецЦикла;

Поиск, проверка и удаление элементов

Метод Найти(Значение) возвращает индекс первого найденного элемента или Неопределено, если элемента нет. Сравнение идёт строгое: строка «10» не равна числу 10, а ссылки на разные объекты с одинаковым представлением считаются разными. Перед поиском убедитесь, что тип искомого значения совпадает с типом элементов массива.

Для удаления есть два метода: Удалить(Индекс) — по позиции и связка Найти + Удалить — по значению. Метод Очистить() удаляет все элементы, оставляя пустой массив. Попытка удалить несуществующий индекс вызовет ошибку выполнения, поэтому всегда проверяйте результат Найти на Неопределено.

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

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

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

КонецЕсли;

// Проверка границ перед обращением по индексу

Если Индекс >= 0 И Индекс < Товары.Количество() Тогда

Значение = Товары[Индекс];

КонецЕсли;

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

Типичные ошибки
01
Обращение к элементу без проверки границ: Товары[Товары.Количество()] вызывает ошибку, потому что последний допустимый индекс — Количество()-1
02
Поиск значения другого типа: Найти("5") не найдёт число 5, и код молча пойдёт по ветке «не найдено»
03
Изменение массива в вызванной процедуре и ожидание, что изменения видны снаружи: массив передаётся по значению, копия изменяется, оригинал нет
04
Удаление элементов в прямом цикле: после Удалить индексы сдвигаются, и следующий элемент пропускается

Передача массива в процедуры и функции

В отличие от таблицы значений или структуры, массив в 1С передаётся по значению. Когда вы передаёте массив параметром, вызываемая процедура получает полную копию. Изменения копии не отражаются на исходном массиве, а на больших объёмах копирование съедает память и время.

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

Функция ДобавитьОтбор(Знач МассивОтборов, НовыйОтбор)

МассивОтборов.Добавить(НовыйОтбор);

Возврат МассивОтборов;

КонецФункции

// Вызов с переприсвоением

Отборы = ДобавитьОтбор(Отборы, "Склад");

Полезные приёмы: граница, выгрузка из запроса, соединение массивов

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

Запрос = Новый Запрос("ВЫБРАТЬ Ссылка ИЗ Документ.РеализацияТоваровУслуг");

МассивСсылок = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");

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

Для проверки массива на пустоту используйте Количество() = 0. Не сравнивайте массив с Неопределено — созданный, но пустой массив не равен Неопределено, и такая проверка всегда даст ложный результат.

Порядок действий при заполнении массива из запроса
  1. 1
    Сформируйте текст запроса и установите параметры
  2. 2
    Выполните запрос и выгрузите результат в таблицу значений методом Выгрузить()
  3. 3
    Получите массив методом ВыгрузитьКолонку с именем нужной колонки
  4. 4
    Проверьте Массив.Количество() > 0 перед дальнейшей обработкой
  5. 5
    Если массив передаётся параметром в другой запрос — убедитесь, что типы элементов соответствуют полю сравнения

Массив или другая коллекция: как выбрать

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

КоллекцияКогда использоватьОграничение
МассивУпорядоченный набор значений, обход по индексуПередаётся по значению, медленный поиск
Список значенийИнтерактивный выбор, пометки, представленияТяжелее массива, избыточен для служебных данных
СоответствиеБыстрый поиск по ключу, устранение дублейПорядок обхода не гарантирован
Таблица значенийТабличные данные, отборы, сортировка, свёрткаЗаметно больше накладных расходов

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

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

Массив

Подходит для упорядоченных однотипных значений и передачи списков параметров. Ограничение: копируется при передаче в процедуры, линейный поиск.

Соответствие

Подходит для поиска по ключу и удаления дублей. Ограничение: нет гарантированного порядка обхода и доступа по индексу.

Таблица значений

Подходит для многоколоночных данных, отборов и свёрток. Ограничение: больше памяти и кода для простых задач.

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

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

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

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

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

Количество элементов после заполнения
Норма

Совпадает с числом строк источника данных

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

Меньше ожидаемого — возможен пропуск при обходе или удалении в прямом цикле

Значения элементов в отладчике
Норма

Все элементы заполнены значениями нужного типа

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

Есть Неопределено — массив создан с размером, но не заполнен полностью

Массив после вызова процедуры
Норма

Используется возвращённое функцией значение

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

Проверяется исходная переменная — изменения копии в ней не видны

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

Итог

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

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

Частые вопросы о массивах в 1С

Как отсортировать массив в 1С?

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

Как узнать, пуст ли массив?

Проверяйте условие Массив.Количество() = 0. Сравнение с Неопределено не работает: созданный конструктором массив — это объект, даже если в нём нет элементов. Если переменная может быть вообще не инициализирована, сначала проверьте её на Неопределено, а уже потом обращайтесь к методу Количество.

Почему изменения массива внутри процедуры не видны снаружи?

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

Как удалить дубли из массива?

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

Можно ли хранить в массиве элементы разных типов?

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

Что быстрее: массив или таблица значений?

Для простого хранения и обхода однотипных значений массив легче и быстрее. Таблица значений выигрывает, когда нужны отборы, сортировка, свёртка и поиск по индексированным колонкам — ручная реализация этих операций на массиве будет медленнее и сложнее. Выбирайте структуру под операции, а не под объём данных.