Как создать и использовать многомерный массив в 1С:Предприятие?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Особенности устройства массивов в 1С

В платформе 1С объект Массив является динамическим одномерным списком элементов. Конструктор массива позволяет объявить многомерную структуру, передав параметры размеров через запятую, например Новый Массив(3, 2). Однако важно понимать, как именно это работает:

  1. Нельзя пропускать параметры: Конструкция вида Новый Массив(, 2) вызовет синтаксическую ошибку, так как платформа требует явного указания целочисленных размеров для каждого измерения.
  2. Инициализация значениями по умолчанию: При создании массива с фиксированными размерами память выделяется сразу, и все ячейки заполняются значением Неопределено. Поэтому свойство Количество() вернет изначально заданный размер, даже если реальные данные туда еще не записаны.
  3. Многомерный массив — это массив массивов: Обращение вида Массив[0][1] означает, что мы обращаемся к нулевому элементу внешнего массива, который сам по себе является вложенным массивом, и читаем его первый элемент.

Способ 1. Динамический массив массивов

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


// Создаем основной внешний массив
ДвумерныйМассив = Новый Массив;

// Добавляем строки динамически
Строка1 = Новый Массив;
Строка1.Добавить(1);     // Порядковый номер
Строка1.Добавить("+");   // Знак операции
ДвумерныйМассив.Добавить(Строка1);

Строка2 = Новый Массив;
Строка2.Добавить(5);
Строка2.Добавить("*");
ДвумерныйМассив.Добавить(Строка2);

// Обращение к элементам: [индекс_строки][индекс_колонки]
Сообщить("Символ операции: " + ДвумерныйМассив[1][1]);

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

Способ 2. Использование одномерного массива с вычислением индекса

Проанализируем альтернативный подход, часто применяемый в классическом программировании для ускорения работы с памятью. Мы можем выделить один одномерный массив и адресовать его ячейки математически по формуле Индекс = (НомерСтроки * КоличествоКолонок) + НомерКолонки.

Посмотрим на пример работы с таблицей из 2 колонок:


КоличествоКолонок = 2;
КоличествоСтрок = 3;
Массив = Новый Массив(КоличествоСтрок * КоличествоКолонок);

// Заполняем строку 0 (колонки 0 и 1)
Массив[0 * КоличествоКолонок + 0] = 1;
Массив[0 * КоличествоКолонок + 1] = "+";

// Заполняем строку 1 (колонки 0 и 1)
Массив[1 * КоличествоКолонок + 0] = 6;
Массив[1 * КоличествоКолонок + 1] = "*";

// Получаем операцию из второй строки (индекс строки 1, колонка 1)
Операция = Массив[1 * КоличествоКолонок + 1];
Сообщить("Операция: " + Операция);

Способ 3. Массив структур (наиболее читаемый вариант)

Когда требуется хранить пары или кортежи связанных данных (например, «Позиция» и «Оператор»), лучшей практикой в 1С является использование одномерного массива структур. Это делает код наглядным и защищает от ошибок обращения по числовым индексам.


СписокОпераций = Новый Массив;

// Добавляем найденную операцию
Операция = Новый Структура;
Операция.Вставить("Позиция", 1);
Операция.Вставить("Символ", "+");
СписокОпераций.Добавить(Операция);

// Обход элементов
Для Каждого Элемент Из СписокОпераций Цикл
    Сообщить("Символ: " + Элемент.Символ + " на позиции " + Элемент.Позиция);
КонецЦикла;

Способ 4. Таблица значений

Если логика выполняется на стороне сервера, для табличных данных отлично подходит ТаблицаЗначений. Обратите внимание: объект ТаблицаЗначений недоступен на тонком клиенте в управляемом приложении.


// Доступно только в серверном контексте (&НаСервере)
Тбл = Новый ТаблицаЗначений;
Тбл.Колонки.Добавить("Позиция", Новый ОписаниеТипов("Число"));
Тбл.Колонки.Добавить("Оператор", Новый ОписаниеТипов("Строка"));

НоваяСтрока = Тбл.Добавить();
НоваяСтрока.Позиция = 1;
НоваяСтрока.Оператор = "+";

Типичная ошибка: удаление элементов массива в цикле

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

Разберем два правильных способа очистки массива:

  1. Обратный цикл (с конца в начало): Смещение индексов затрагивает только элементы справа от текущего, поэтому удаление с конца не ломает индексацию еще не проверенных элементов.
  2. Копирование в новый массив: Фильтрация данных с добавлением только валидных значений в чистый массив.

Рассмотрим реализацию обратного цикла:


// Пример правильного удаления пустых элементов через обратный цикл
Для Счетчик = -(Массив.Количество() - 1) По 0 Цикл
    Индекс = -Счетчик;
    Если ПустаяСтрока(Массив[Индекс][0]) Тогда
        Массив.Удалить(Индекс);
    КонецЕсли;
КонецЦикла;

Реализация стека для вычисления выражений (ОПЗ)

При построении собственного интерпретатора выражений или калькулятора со скобками стандартным подходом является алгоритм сортировочной станции Дейкстры и преобразование в обратную польскую запись (ОПЗ). Для вычисления выражений в ОПЗ необходим стек.

В 1С стек легко эмулируется обычным динамическим массивом по принципу LIFO (последний пришел — первый ушел):


Стек = Новый Массив;

// Помещение значения в стек (Push)
Стек.Добавить(3);
Стек.Добавить(4);

// Извлечение значения с вершины стека (Pop)
ИндексВершины = Стек.Количество() - 1;
Операнд2 = Стек[ИндексВершины];
Стек.Удалить(ИндексВершины);

ИндексВершины = Стек.Количество() - 1;
Операнд1 = Стек[ИндексВершины];
Стек.Удалить(ИндексВершины);

// Вычисление и возврат результата в стек
Результат = Операнд1 + Операнд2;
Стек.Добавить(Результат);

Альтернатива: использование функции Вычислить

Если задача заключается исключительно в получении результата математического выражения без необходимости вручную парсить лексемы, платформа 1С предоставляет встроенную функцию Вычислить(), которая способна выполнять простые математические расчеты со скобками и базовыми арифметическими знаками:


СтрокаФормулы = "3 + 4 * 2 / (1 - 5)";
Результат = Вычислить(СтрокаФормулы);
Сообщить("Результат: " + Результат);
← На главную