Часто в процессе разработки возникает задача уникализации данных в коллекции Массив. У этой универсальной коллекции в 1С нет встроенных методов для автоматической уникализации, таких как метод Свернуть(), который доступен для таблицы значений. Рассмотрим подробнее, почему возникают ошибки при попытке очистить массив от дублей "на месте", и разберем несколько проверенных способов решения этой задачи.
Проанализируем частую ошибку начинающих разработчиков — попытку удалить дубликаты, перебирая массив с помощью цикла Для Каждого или прямого цикла по индексам Для Индекс = 0 По Количество - 1. Главная проблема кроется в том, что при удалении любого элемента из коллекции происходит неявное смещение индексов: все элементы, расположенные правее удаленного, сдвигаются на одну позицию влево, чтобы заполнить пустоту.
Так как итератор цикла при этом продолжает двигаться вперед, элемент, вставший на место удаленного, пропускается и вообще не обрабатывается алгоритмом. Кроме того, прямое удаление при обходе оператором Для Каждого часто приводит к непредсказуемым результатам или ошибкам выхода за границы коллекции. Выясним, как сделать это правильно, если стоит жесткое условие не создавать новые коллекции.
Если необходимо модифицировать исходный массив без создания дополнительных структур данных, единственным корректным алгоритмом является обратный обход массива — от конца к началу. Посмотрим на логику такого обхода по шагам:
Пример реализации алгоритма:
Индекс = Массив.ВГраница();
Пока Индекс >= 0 Цикл
ТекущееЗначение = Массив[Индекс];
ИндексПервогоВхождения = Массив.Найти(ТекущееЗначение);
// Если элемент найден ближе к началу массива, значит текущий элемент — это дубль
Если ИндексПервогоВхождения < Индекс Тогда
Массив.Удалить(Индекс);
КонецЕсли;
Индекс = Индекс - 1;
КонецЦикла;
Разберем гораздо более простой и быстрый способ уникализации, если создание новых коллекций допустимо. Объект Соответствие устроен таким образом, что ключи в нем всегда уникальны. Мы можем использовать значения массива в качестве ключей соответствия, а затем выгрузить эти ключи обратно в новый массив.
Функция СвернутьМассив(пМассив)
Уник = Новый Соответствие;
Для Каждого Значение Из пМассив Цикл
Уник.Вставить(Значение, Истина);
КонецЦикла;
Рез = Новый Массив;
Для Каждого КлючЗначение Из Уник Цикл
Рез.Добавить(КлючЗначение.Ключ);
КонецЦикла;
Возврат Рез;
КонецФункции
Еще один классический вариант — задействовать объект ТаблицаЗначений. У него есть встроенный метод Свернуть(). Этот способ отлично подходит, если в дальнейшем уникализированные данные удобнее обрабатывать именно в виде таблицы.
Табло = Новый ТаблицаЗначений;
Табло.Колонки.Добавить("НашПараметр");
// Загружаем наш массив в единственную колонку таблицы
Табло.ЗагрузитьКолонку(ПараметрыЗапроса, "НашПараметр");
// Сворачиваем таблицу по этой колонке
Табло.Свернуть("НашПараметр", "");
// Если нужен обратно массив, можно использовать:
// МассивУникальных = Табло.ВыгрузитьКолонку("НашПараметр");
Если в вашей конфигурации внедрена Библиотека Стандартных Подсистем (БСП), нет необходимости изобретать велосипед. Разработчики 1С уже предусмотрели готовую функцию для этой задачи. Просто используйте метод общего модуля:
ОбщегоНазначенияКлиентСервер.СвернутьМассив(ВашМассивСДублями);
Эта функция самостоятельно удалит все дубликаты, оставив в переданном массиве только уникальные значения. Применение стандартизированных функций БСП всегда предпочтительнее, так как это делает код более читаемым и сокращает время на разработку.