При разработке алгоритмов обработки коллекций в 1С иногда возникают специфические алгоритмические задачи — например, смещение диапазона элементов массива от индекса a до индекса b на n позиций при жестком ограничении на создание дополнительных буферных переменных.
Рассмотрим особенности платформы 1С:Предприятие при работе с массивами, разберем возможные сценарии (линейный сдвиг с перезаписью, циклический сдвиг числовых и произвольных данных) и проанализируем оптимальные платформенные подходы.
Прежде чем перейти к алгоритмам, выясним базовые ограничения и свойства типа Массив в 1С:
0 до Количество() - 1).m в 1С применяется конструкция с платформенной функцией Цел(): Индекс - Цел(Индекс / m) * m.Если задача предполагает смещение элементов с перезаписью целевых ячеек (без сохранения вытесняемых данных), решение сводится к выбору правильного направления обхода цикла. Это позволяет обойтись исключительно счетчиком цикла без создания вспомогательных переменных.
Разберем логику выбора направления:
n > 0): Обход необходимо выполнять строго в обратном порядке — с конца диапазона к началу с шагом -1. В этом случае значение читается из исходного индекса и записывается в целевой до того, как исходный индекс будет перезаписан предыдущим шагом.n < 0): Обход выполняется в прямом порядке — от начала диапазона к концу.Посмотрим на пример кода сдвига вправо диапазона от a до b на n позиций:
// Сдвиг элементов от a до b вправо на n позиций
Для Счетчик = b + n По a + n Шаг -1 Цикл
Массив[Счетчик] = Массив[Счетчик - n];
КонецЦикла;
Рассмотрим работу алгоритма по шагам: сначала элемент b копируется в позицию b + n, затем b - 1 копируется в b + n - 1, и так далее до первого элемента a, попадающего в позицию a + n. Дополнительная память под промежуточные значения не выделяется.
Если массив состоит строго из числовых значений и требуется выполнить циклический обмен элементов внутри массива без создания промежуточных переменных в памяти, можно применить классический арифметический метод обмена значений (через сложение и вычитание).
Разберем математический принцип: для двух чисел X и Y обмен без третьей переменной выполняется в три операции: X = X + Y, затем Y = X - Y, затем X = X - Y.
Посмотрим на реализацию циклического сдвига элементов с a по b на n позиций в массиве длины m:
Счетчик = a;
Пока Счетчик <= b Цикл
ЦелевойИндекс = Счетчик + n - Цел((Счетчик + n) / m) * m;
Массив[Счетчик] = Массив[Счетчик] + Массив[ЦелевойИндекс];
Массив[ЦелевойИндекс] = Массив[Счетчик] - Массив[ЦелевойИндекс];
Массив[Счетчик] = Массив[Счетчик] - Массив[ЦелевойИндекс];
Счетчик = Счетчик + 1;
КонецЦикла;
Важный момент: Данный способ применим исключительно к числовым типам данных. Для строк, ссылок и структур арифметический обмен не работает.
В реальной прикладной разработке на платформе 1С:Предприятие для перемещения элементов коллекции эффективнее использовать встроенные методы объекта Массив. Внутренняя реализация платформы выполняет перемещение элементов на уровне ядра C++, что работает значительно быстрее любых ручных циклов.
Платформа предоставляет следующие методы:
Массив.Вставить(Индекс, Значение) — вставляет элемент в указанную позицию, автоматически сдвигая все последующие элементы вправо.Массив.Удалить(Индекс) — удаляет элемент по индексу со смещением всех последующих элементов влево.Проанализируем пример перемещения элемента с позиции ИсходныйИндекс на позицию ЦелевойИндекс:
Значение = Массив[ИсходныйИндекс];
Массив.Удалить(ИсходныйИндекс);
Массив.Вставить(ЦелевойИндекс, Значение);
Такой подход обеспечивает максимальную читаемость кода, исключает ошибки выхода за границы массива и соответствует стандартам разработки 1С.