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

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

Массивы в 1С: устройство, методы и практические приёмы

Что такое массив в 1С: создание, добавление и перебор элементов, методы Количество, Найти, Удалить, работа с индексами и типичные ошибки разработчиков.

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

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

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

Что такое массив и когда он нужен

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

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

Типичные сценарии применения массивов:

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

Как создать массив и добавить элементы

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

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

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

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

МассивФиксированный = Новый Массив(10);

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

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

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

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

Метод Добавить() возвращает ссылку на добавленный элемент, что иногда удобно, но чаще всего возвращаемое значение просто игнорируют. Обращение к элементу выполняется по индексу через квадратные скобки: МассивТоваров[0].

Порядок действий
  1. 1
    Создайте массив: Массив = Новый Массив();
  2. 2
    Добавьте элементы методом Добавить(Значение);
  3. 3
    Обратитесь к элементу по индексу: Массив[0];
  4. 4
    Проверьте размер: Массив.Количество();
  5. 5
    Переберите элементы циклом Для Каждого Элемент Из Массив Цикл.

Основные методы массива

У массива компактный, но достаточный для большинства задач набор методов. Знание границ их применимости избавляет от изобретения велосипедов и от ошибок с выходом за пределы коллекции.

МетодЧто делаетОсобенность
Количество()Возвращает число элементовПоследний индекс = Количество() − 1
Добавить(Значение)Добавляет элемент в конецВозвращает добавленный элемент
Вставить(Индекс, Значение)Вставляет элемент в позициюИндекс за пределами — ошибка
Найти(Значение)Возвращает индекс первого вхожденияЕсли не найдено — Неопределено
Удалить(Индекс)Удаляет элемент по индексуИндексы остальных сдвигаются
Очистить()Удаляет все элементыКоличество() станет 0
ВГраница()Возвращает индекс последнего элементаДля пустого массива = −1
Получить(Индекс) / Установить(Индекс, Значение)Чтение и запись элементаЭквивалентны Массив[Индекс]

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

Индекс = МассивТоваров.Найти(ИскомаяСсылка);

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

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

КонецЕсли;

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

Самый безопасный способ перебора — цикл Для Каждого … Из … Цикл. Он не требует работы с индексами, поэтому исключает выход за границы массива:

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

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

КонецЦикла;

Если нужен индекс элемента или требуется изменять элементы по позиции, используют цикл со счётчиком:

Для Инд = 0 По МассивТоваров.ВГраница() Цикл

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

КонецЦикла;

Удаление элементов внутри цикла

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

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

Массивы в запросах и передача данных

Одно из самых продуктивных применений массива — передача его как параметра в запрос для условия В(). Платформа сама разворачивает массив в список значений, что избавляет от конструирования длинных условий «ИЛИ»:

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| Номенклатура.Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|ГДЕ

| Номенклатура.Ссылка В (&СписокСсылок)";

Запрос.УстановитьПараметр("СписокСсылок", МассивСсылок);

В обратную сторону — чтобы получить массив значений одной колонки из результата запроса — применяют связку Выгрузить() и ВыгрузитьКолонку():

Результат = Запрос.Выполнить().Выгрузить();

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

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

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

Массив — не единственная коллекция в 1С, и не всегда оптимальная. Выбор зависит от того, как данные будут использоваться.

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

Массив

Универсален, работает на клиенте и сервере, быстрый доступ по индексу. Неудобен для частого поиска и хранения структурированных записей.

СписокЗначений

Подходит, когда нужны представления элементов, пометки и сортировка по представлению; доступен на клиенте. Тяжелее массива.

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

Когда нужен быстрый поиск по ключу (аналог словаря). Порядок обхода не гарантирован.

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

Когда данные табличные: несколько колонок, поиск, сортировка, свёртка. Недоступна на тонком клиенте.

ФиксированныйМассив

Неизменяемый массив; подходит для возврата данных, которые вызывающий код не должен менять.

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

Многомерные массивы и массивы структур

В 1С нет отдельного типа «двумерный массив», но массив может содержать другие массивы. Так моделируют матрицы:

Матрица = Новый Массив();

Для И = 1 По 3 Цикл

Строка = Новый Массив();

Для Ж = 1 По 3 Цикл

Строка.Добавить(0);

КонецЦикла;

Матрица.Добавить(Строка);

КонецЦикла;

Матрица[0][1] = 5;

Другой распространённый приём — массив структур. Он заменяет таблицу значений там, где таблица недоступна (тонкий клиент) или избыточна:

Запись = Новый Структура("Товар, Количество", СсылкаНаТовар, 10);

МассивДанных.Добавить(Запись);

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

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

При работе с массивами полезно проверять состояние коллекции до и после операций. Минимальный набор контрольных точек:

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

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

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

Количество() совпадает с ожидаемым числом записей (например, с числом строк выборки)

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

Количество() = 0 при непустом источнике или больше ожидаемого — проверяйте условие добавления

Обращение по индексу
Норма

Индекс в диапазоне 0 … ВГраница()

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

Ошибка «Индекс находится за границами массива» — проверьте условие цикла

Результат Найти()
Норма

Возвращён числовой индекс

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

Возвращено Неопределено — элемент не найден, обработайте этот случай

Содержимое после удаления
Норма

Удалены именно нужные элементы, остальные на месте

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

Пропущены или удалены лишние элементы — вероятно, удаление в прямом цикле

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

Итог

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

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

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

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

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

Как узнать индекс последнего элемента массива?

Методом ВГраница() — он возвращает Количество() − 1. Для пустого массива ВГраница() вернёт −1, поэтому цикл «Для Инд = 0 По Массив.ВГраница()» корректно не выполнится ни разу.

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

Да, ограничений по типам нет: в одном массиве могут быть строки, числа и ссылки. Но обработка такого массива потребует проверки типа каждого элемента через ТипЗнч(), что усложняет код. Однородные массивы предпочтительнее.

Как скопировать массив, чтобы изменения копии не затрагивали оригинал?

Присваивание НовыйМассив = СтарыйМассив копирует только ссылку — обе переменные будут указывать на один объект. Для независимой копии создайте новый массив и перенесите элементы циклом «Для Каждого». Учтите, что сами элементы-ссылки на объекты БД при этом не дублируются — копируется только набор ссылок.

Что вернёт метод Найти(), если элемент встречается несколько раз?

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

Почему возникает ошибка «Индекс находится за границами массива»?

Причина всегда одна: обращение по индексу, которого нет в массиве — отрицательному или большему, чем ВГраница(). Чаще всего это результат цикла до Количество() вместо Количество() − 1, обращения к пустому массиву или использования результата Найти() без проверки на Неопределено.