Массив в 1С 8.3: создание, заполнение и методы работы
Содержание
Пустой массив создаётся одной строкой: Массив = Новый Массив;. Если сразу известно, сколько элементов нужно, в конструктор передают число: Новый Массив(10) даёт массив на 10 элементов с индексами от 0 до 9. Добавляют значения методом Добавить, читают по индексу через квадратные скобки, перебирают циклом Для Каждого.
Массив во встроенном языке 1С 8.3 — это упорядоченный набор значений любого типа с доступом по числовому индексу. Нумерация всегда начинается с нуля. Ниже разберём, как объявить массив, заполнить его заранее известным размером, собрать фиксированный и многомерный массив, какие у него есть методы и почему он ведёт себя как ссылка, а не как значение.
Создание массива: конструктор Новый Массив
Базовая форма объявления — вызов конструктора без параметров. Так получается пустой массив, в который элементы добавляются по ходу работы:
Массив = Новый Массив;
Массив.Добавить("Яблоко");
Массив.Добавить("Груша");
Массив.Добавить(150);
Сообщить(Массив.Количество()); // 3
Обратите внимание: в одном массиве спокойно лежат и строки, и число. Типизация элементов свободная — язык не требует, чтобы весь набор был однородным.
Чтение значения — по индексу. Два способа равнозначны:
Первый = Массив[0]; // "Яблоко"
Второй = Массив.Получить(1); // "Груша"
Запись в существующий элемент — так же, через скобки или метод Установить:
Массив[2] = 200;
Массив.Установить(0, "Слива");
Индекс последнего элемента всегда равен Количество() - 1. Попытка обратиться к Массив[Массив.Количество()] вызовет ошибку «Индекс находится за границами массива».
Массив заданного размера и его заполнение
Когда число элементов известно заранее, размер задают прямо в конструкторе. Все ячейки при этом получают значение Неопределено:
Дни = Новый Массив(7);
Сообщить(Дни[0]); // Неопределено
Такой массив удобно заполнять циклом по индексу. Верхнюю границу даёт метод ВГраница — он возвращает индекс последнего элемента (для пустого массива это −1):
Дни = Новый Массив(7);
Для Сч = 0 По Дни.ВГраница() Цикл
Дни[Сч] = СтрШаблон("День %1", Сч + 1);
КонецЦикла;
Число и строку нельзя складывать напрямую: "День " + 1 приведёт к ошибке типа. Поэтому в примере используется СтрШаблон, который сам приводит число к строке. Альтернатива — явное преобразование: "День " + Строка(Сч + 1).
Разница между двумя способами объявления принципиальная:
| Конструктор | Что получаем | Когда применять |
|---|---|---|
Новый Массив | Пустой, 0 элементов | Размер заранее не известен, элементы добавляем по мере обработки |
Новый Массив(N) | N ячеек со значением Неопределено | Количество известно, индексы нужны сразу |
Если заполнять заранее размеченный массив через Добавить, он вырастет за пределы N — метод всегда дописывает в конец, а не замещает пустые ячейки. Это частая причина лишних элементов Неопределено в начале.
Фиксированный массив: когда нужен неизменяемый список
ФиксированныйМассив — это массив, который нельзя менять после создания. Его собирают из обычного массива, передав тот в конструктор:
Исходный = Новый Массив;
Исходный.Добавить("Красный");
Исходный.Добавить("Зелёный");
Исходный.Добавить("Синий");
Цвета = Новый ФиксированныйМассив(Исходный);
Сообщить(Цвета.Количество()); // 3
Сообщить(Цвета[1]); // "Зелёный"
Читать из фиксированного массива можно теми же способами — по индексу, через Получить, перебором в цикле, методом Найти. А вот Добавить, Удалить, Вставить и присваивание по индексу вызовут ошибку: набор защищён от изменения.
Зачем он нужен:
- 🔒 Передача списка в процедуру, где он не должен случайно измениться.
- 📌 Константные перечни — например, набор допустимых статусов или кодов.
- ♻️ Параметры, которые по смыслу настраиваются один раз.
После упаковки в фиксированный массив связь с исходным теряется: изменения в Исходный на Цвета уже не влияют.
Чтобы снова получить изменяемую версию, соберите из фиксированного обычный массив перебором:
Изменяемый = Новый Массив;
Для Каждого Элемент Из Цвета Цикл
Изменяемый.Добавить(Элемент);
КонецЦикла;
Фиксированные массивы часто приходят «снаружи» — из системных свойств платформы и параметров сеанса. Если такой массив нужно дополнить, этот приём с перекладыванием в обычный массив — штатный способ.
Многомерные и вложенные массивы
Многомерный массив получают, передав в конструктор несколько размеров через запятую. Запись Новый Массив(3, 2) создаёт три элемента, каждый из которых сам является массивом из двух ячеек:
Матрица = Новый Массив(3, 2);
Матрица[0][0] = 1;
Матрица[0][1] = 2;
Матрица[1][0] = 3;
Сообщить(Матрица[0][1]); // 2
Доступ к ячейке — через двойные скобки: сначала строка, потом столбец. По сути это массив массивов, и ту же структуру легко собрать вручную, если размеры заранее не фиксированы:
Таблица = Новый Массив;
Для НомерСтроки = 1 По 3 Цикл
Строка = Новый Массив;
Строка.Добавить("Код");
Строка.Добавить("Наименование");
Таблица.Добавить(Строка);
КонецЦикла;
Ручной способ гибче: строки могут быть разной длины, а в ячейках — любые значения, включая структуры и ссылки на объекты.
Обходят двумерный массив вложенными циклами — внешний по строкам, внутренний по ячейкам строки:
Для Каждого Строка Из Матрица Цикл
Для Каждого Ячейка Из Строка Цикл
Сообщить(Ячейка);
КонецЦикла;
КонецЦикла;
Такая конструкция не зависит от числа столбцов и работает даже с «рваными» массивами, где строки разной длины.
Если данные по смыслу табличные (строки с одинаковым набором колонок), чаще удобнее ТаблицаЗначений с именованными колонками, чем вложенный массив с числовыми индексами. Читать Строка.Количество понятнее, чем помнить, что [2] — это цена.
Как получить массив из строки или таблицы
Конструктор — не единственный путь. Готовый массив возвращают несколько штатных методов, и это самый частый способ получить его на практике.
Разбор строки. Метод СтрРазделить режет строку по разделителю и отдаёт массив строк:
Коды = СтрРазделить("10;20;30", ";");
Сообщить(Коды.Количество()); // 3
Сообщить(Коды[0]); // "10" (строка, не число)
Элементы здесь — строки, поэтому перед арифметикой их приводят к числу через Число(). Третий параметр СтрРазделить управляет тем, включать ли пустые подстроки.
Колонка таблицы значений. Метод ВыгрузитьКолонку собирает значения одной колонки в массив:
МассивАртикулов = ТаблицаТоваров.ВыгрузитьКолонку("Артикул");
Результат запроса. Та же пара методов работает после запроса: сначала результат выгружают в таблицу, затем берут из неё колонку:
Выборка = Запрос.Выполнить().Выгрузить();
МассивСсылок = Выборка.ВыгрузитьКолонку("Номенклатура");
Так получается массив ссылок, который удобно передать в параметр другого запроса (Номенклатура В (&МассивСсылок)) или в отбор формы. Это основной приём, когда массив нужен не сам по себе, а как набор отобранных данных.
Методы массива: добавить, найти, удалить, перебрать
Полный набор операций над элементами компактен. Вот основные методы:
- ➕
Добавить(Значение)— дописать в конец. - ⤵️
Вставить(Индекс, Значение)— вставить на позицию, сдвинув остальные вправо. - ➖
Удалить(Индекс)— убрать элемент по индексу. - 🔍
Найти(Значение)— вернуть индекс первого совпадения илиНеопределено, если значения нет. - 🔢
Количество()— число элементов. - 📏
ВГраница()— индекс последнего элемента (−1 для пустого). - 🧹
Очистить()— удалить все элементы.
Поиск удобно сочетать с проверкой на Неопределено:
Индекс = Массив.Найти("Груша");
Если Индекс <> Неопределено Тогда
Массив.Удалить(Индекс);
КонецЕсли;
Вставка в середину сдвигает все последующие элементы вправо, поэтому индексы после точки вставки меняются:
Массив = Новый Массив;
Массив.Добавить("А");
Массив.Добавить("В");
Массив.Вставить(1, "Б"); // теперь ["А", "Б", "В"]
Перебрать массив можно двумя циклами. Когда индекс не важен — коротким Для Каждого:
Для Каждого Элемент Из Массив Цикл
Сообщить(Элемент);
КонецЦикла;
Когда нужен именно номер элемента — циклом по индексу от 0 до ВГраница.
Отдельный случай — удаление элементов во время обхода. Менять массив внутри Для Каждого нельзя: возникнет ошибка «Запрещено изменение коллекции во время обхода». Удаляют с конца обычным циклом, чтобы индексы оставшихся элементов не смещались:
Сч = Массив.ВГраница();
Пока Сч >= 0 Цикл
Если Массив[Сч] = Неопределено Тогда
Массив.Удалить(Сч);
КонецЕсли;
Сч = Сч - 1;
КонецЦикла;
Проход от конца к началу важен: если удалять с нулевого элемента вперёд, после каждого Удалить оставшиеся сдвигаются, и часть элементов цикл пропустит.
Типизация, ссылки и производительность
Массив хранит значения любых типов вперемешку — ограничений на однородность нет. Но у этой гибкости есть две особенности, из-за которых возникают неочевидные ошибки.
Массив — ссылочный тип. Присваивание не копирует данные, а передаёт ссылку на тот же набор:
А = Новый Массив;
А.Добавить(1);
Б = А; // Б и А указывают на один и тот же массив
Б.Добавить(2);
Сообщить(А.Количество()); // 2, не 1
То же касается передачи массива в процедуру: изменения внутри неё видны снаружи. Если нужна независимая копия — соберите новый массив перебором элементов исходного. Учтите: такой перебор копирует только верхний уровень. Если в ячейках лежат вложенные массивы или структуры, копии разделят с оригиналом те же вложенные объекты, и для полной независимости их придётся копировать отдельно.
Производительность зависит от операции. Полезно держать в голове порядок стоимости:
| Операция | Стоимость | Комментарий |
|---|---|---|
Добавить | Дёшево | Дописывание в конец |
Доступ по индексу [i] | Дёшево | Прямой адрес |
Вставить / Удалить в середине | Дорого на больших массивах | Сдвигает все последующие элементы |
Найти | Линейный перебор | Чем длиннее массив, тем дольше |
Если по коллекции нужен частый поиск по ключу, а не по индексу, массив — не лучший выбор. Для этого есть Соответствие, где значение достаётся сразу по ключу:
Цены = Новый Соответствие;
Цены.Вставить("Яблоко", 150);
Цены.Вставить("Груша", 200);
Сообщить(Цены["Груша"]); // 200, без перебора
В массиве тот же поиск означал бы линейный проход всех элементов через Найти. Правило простое: нужен порядок и последовательный обход — берите массив; нужен быстрый доступ по ключу — соответствие.
Типичные ошибки при работе с массивом
Ошибки здесь повторяются из версии в версию и легко диагностируются по тексту сообщения:
- 🚫 «Индекс находится за границами массива» — обращение к несуществующему элементу. Чаще всего это
[Количество()]вместо[Количество() - 1]или чтение из пустого массива. - 🚫 «Запрещено изменение коллекции во время обхода» — вызов
Удалить,ДобавитьилиОчиститьвнутриДля Каждого. Лечится обычным циклом с конца. - 🚫 Молчаливое изменение «чужого» массива — следствие ссылочной природы: передали массив в функцию, та его изменила. Если это нежелательно, передавайте копию.
- 🚫 Попытка изменить
ФиксированныйМассив— любой из методов записи вызовет ошибку. Создайте из него обычный массив.
Частые вопросы
Чем массив отличается от соответствия и таблицы значений?
Соответствие хранит пары «ключ — значение» и быстро ищет по ключу. ТаблицаЗначений — набор строк с именованными колонками. Для последовательной обработки берите массив, для поиска по ключу — соответствие, для табличных данных — таблицу значений.Как отсортировать массив?
СписокЗначений или ТаблицуЗначений и вызывают их штатную сортировку, после чего при необходимости собирают результат обратно в массив.Как скопировать массив, чтобы оригинал не менялся?
Как проверить, что массив пустой?
Массив.Количество() с нулём. Метод ВГраница() у пустого массива вернёт −1.