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

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

Как убрать повторяющиеся элементы из массива в 1С

Способы удалить дубли из массива в 1С: через Соответствие, СписокЗначений, ТаблицуЗначений и Свернуть(). Примеры кода, сравнение методов и типичные ошибки.

Повторяющиеся значения в массиве — типовая задача при разработке на платформе 1С:Предприятие. Дубли появляются при объединении результатов нескольких запросов, при обходе табличных частей документов, при сборе ссылок из разных источников. Если не очистить массив, дальнейшие операции — сравнение, запись в базу, формирование отчёта — будут работать медленнее или дадут неверный результат.

Встроенного метода «УдалитьДубликаты» у объекта Массив в 1С нет, поэтому задачу решают через промежуточные коллекции: Соответствие, СписокЗначений или ТаблицуЗначений. Каждый подход имеет свои ограничения по типам данных, скорости и сохранению порядка элементов.

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

Почему в массиве появляются дубли и когда их нужно убирать

Дубли возникают в трёх типовых сценариях. Первый — объединение массивов: при последовательном добавлении элементов из нескольких источников пересечения не контролируются. Второй — обход табличных частей: одна и та же номенклатура может встречаться в документе несколько раз. Третий — выгрузка колонки таблицы значений в массив без предварительной свёртки.

Очищать массив обязательно перед передачей в запрос в качестве параметра (условие В (&СписокЗначений)), перед записью уникальных ссылок в регистры и перед построением отчётов, где дубль даст лишнюю строку. Если массив используется только для однократного перебора без проверки вхождения, удаление дублей иногда можно пропустить — это сэкономит время выполнения.

Способ 1. Удаление дублей через Соответствие

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

Функция УбратьДублиЧерезСоответствие(ИсходныйМассив)

Уникальные = Новый Соответствие;

Для Каждого Элемент Из ИсходныйМассив Цикл

Уникальные.Вставить(Элемент, Истина);

КонецЦикла;

Результат = Новый Массив;

Для Каждого Пара Из Уникальные Цикл

Результат.Добавить(Пара.Ключ);

КонецЦикла;

Возврат Результат;

КонецФункции

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

bsl
Уникальные = Новый Соответствие;
Результат = Новый Массив;
Для Каждого Элемент Из ИсходныйМассив Цикл
    Если Уникальные[Элемент] = Неопределено Тогда
        Уникальные.Вставить(Элемент, Истина);
        Результат.Добавить(Элемент);
    КонецЕсли;
КонецЦикла;

Способ 2. СписокЗначений и метод НайтиПоЗначению

СписокЗначений хранит элементы с возможностью поиска по значению. Алгоритм прост: перебираем массив, проверяем наличие элемента через НайтиПоЗначению и добавляем только отсутствующие. Порядок первых вхождений при этом сохраняется автоматически.

Функция УбратьДублиЧерезСписокЗначений(ИсходныйМассив)

Список = Новый СписокЗначений;

Для Каждого Элемент Из ИсходныйМассив Цикл

Если Список.НайтиПоЗначению(Элемент) = Неопределено Тогда

Список.Добавить(Элемент);

КонецЕсли;

КонецЦикла;

Возврат Список.ВыгрузитьЗначения();

КонецФункции

Главный недостаток — скорость. НайтиПоЗначению выполняет линейный поиск, поэтому на массиве из десятков тысяч элементов время работы растёт квадратично. Для небольших коллекций (до нескольких сотен элементов) разница незаметна, и способ остаётся удобным за счёт читаемости кода.

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

Способ 3. ТаблицаЗначений и метод Свернуть

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

Функция УбратьДублиЧерезТаблицу(ИсходныйМассив)

Таблица = Новый ТаблицаЗначений;

Таблица.Колонки.Добавить("Значение");

Для Каждого Элемент Из ИсходныйМассив Цикл

Таблица.Добавить().Значение = Элемент;

КонецЦикла;

Таблица.Свернуть("Значение");

Возврат Таблица.ВыгрузитьКолонку("Значение");

КонецФункции

При создании колонки без указания типа таблица примет любые значения. Если нужно сворачивать по нескольким полям (например, массив структур «Номенклатура + Склад»), таблица значений — единственный прямой путь: соответствие и список значений сравнивают структуры по ссылке, а не по содержимому, и дубли не найдут.

Способ 4. Запрос с конструкцией РАЗЛИЧНЫЕ

Если массив формируется из данных информационной базы, дубли эффективнее убрать на стороне запроса, а не в коде. Ключевое слово РАЗЛИЧНЫЕ в тексте запроса возвращает только уникальные строки результата, а выгрузка в массив даёт уже очищенную коллекцию.

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

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

"ВЫБРАТЬ РАЗЛИЧНЫЕ

| Продажи.Номенклатура КАК Номенклатура

|ИЗ

| РегистрНакопления.Продажи.Обороты КАК Продажи";

МассивБезДублей = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Номенклатура");

Этот подход переносит работу на сервер СУБД, где дедупликация выполняется оптимизированными средствами. Он предпочтителен, когда источник данных — регистр или табличная часть с большим числом строк. Минус очевиден: способ неприменим к массиву, уже сформированному в памяти, — туда данные придётся сначала поместить во временную таблицу, что обычно избыточно.

Сравнение способов и критерии выбора

СпособСкорость на больших массивахСохранение порядкаПодходящие типы
СоответствиеВысокаяНе гарантируется (вариант с проверкой ключа сохраняет)Любые простые типы и ссылки
СписокЗначенийНизкая при росте объёмаСохраняетсяПростые типы и ссылки
ТаблицаЗначений + СвернутьСредняяНе гарантируетсяЛюбые, включая многополевые
Запрос с РАЗЛИЧНЫЕВысокая на данных из БДТребует УПОРЯДОЧИТЬ ПОДанные из информационной базы

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

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

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

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

Хорош для малых массивов и когда нужно сохранить порядок первых вхождений. На больших объёмах заметно медленнее.

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

Единственный прямой вариант для массивов структур с сравнением по нескольким полям. Требует больше кода.

Запрос с РАЗЛИЧНЫЕ

Оптимален, когда данные ещё не выбраны из базы. Для готового массива в памяти не применяйте.

Маршрут решения

Как выбрать действие

Массив ссылок или простых типов, порядок не важенИспользуйте Соответствие — минимальный код и максимальная скорость
Нужно сохранить порядок первых вхожденийСоответствие с проверкой ключа или СписокЗначений
Элементы — структуры, сравнение по нескольким полямТаблицаЗначений со Свернуть по нужным колонкам
Данные ещё не получены из базыУберите дубли в запросе через РАЗЛИЧНЫЕ

Проверка результата и типичные ошибки

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

Характерная ошибка — попытка удалять элементы из массива внутри цикла перебора по индексу. При удалении текущего элемента индексы сдвигаются, и следующий элемент пропускается. Если удаление в цикле всё же нужно, обход выполняют с конца массива к началу (цикл с шагом -1).

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

Типичные ошибки
01
Удаление элементов массива в прямом цикле по индексу — сдвиг индексов приводит к пропуску элементов. Обходите массив с конца или собирайте новый массив.
02
Использование Соответствия для массива структур — структуры сравниваются по ссылке, дубли по содержимому не находятся. Применяйте ТаблицуЗначений или строковый ключ.
03
Вызов Свернуть без колонок группировки — числовые колонки суммируются, данные искажаются. Всегда указывайте колонки явно.
04
Применение СписокЗначений к массиву из сотен тысяч элементов — квадратичный рост времени поиска. Переходите на Соответствие.
Контрольные точки

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

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

Результат содержит столько элементов, сколько уникальных значений было в исходном массиве

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

Количество не изменилось при заведомых дублях или стало меньше числа уникальных

Уникальность
Норма

Повторный проход по результату не находит совпадений

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

В очищенном массиве остались повторы

Состав данных
Норма

Все уникальные значения исходного массива присутствуют в результате

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

Часть значений потеряна, например из-за неверной свёртки

Производительность и ограничения

На массивах до нескольких сотен элементов разница между способами практически незаметна, и выбор можно делать по удобству чтения кода. При росте объёма до десятков и сотен тысяч элементов линейный поиск в СпискеЗначений становится узким местом, а Соответствие сохраняет приемлемое время работы.

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

Если дедупликация выполняется часто и в разных местах конфигурации, оформите её как функцию в общем модуле с признаком Сервер. Это уберёт дублирование кода и упростит замену алгоритма при изменении требований к порядку элементов.
ПЗ
Практическое замечание

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

Есть ли в 1С встроенный метод удаления дублей из массива?

Нет, у объекта Массив такого метода нет. Задачу решают через промежуточные коллекции — Соответствие, СписокЗначений или ТаблицуЗначений — либо через запрос с конструкцией РАЗЛИЧНЫЕ, если данные берутся из базы.

Как убрать дубли, сохранив порядок элементов?

Используйте Соответствие с проверкой наличия ключа: если ключ ещё не встречался, элемент добавляется и в соответствие, и в результирующий массив. Альтернатива — СписокЗначений с НайтиПоЗначению, который сохраняет порядок по умолчанию.

Как удалить повторы из массива структур?

Напрямую через Соответствие не получится: структуры сравниваются по ссылке, а не по содержимому. Выгрузите поля структур в ТаблицуЗначений и примените Свернуть по нужным колонкам либо сформируйте строковый ключ из значений полей и используйте его в Соответствии.

Что быстрее — Соответствие или СписокЗначений?

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

Можно ли убрать дубли сразу в запросе?

Да. Ключевое слово РАЗЛИЧНЫЕ в тексте запроса возвращает только уникальные строки. Это предпочтительный вариант, когда массив строится из таблиц информационной базы: дедупликация выполняется на стороне СУБД.

Почему после удаления элементов в цикле часть значений осталась?

При удалении элемента по индексу в прямом цикле индексы сдвигаются, и следующий элемент пропускается. Обходите массив с конца к началу или собирайте новый массив без дублей вместо модификации исходного.

Итог

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

Универсальный способ убрать дубли из массива — Соответствие; для сохранения порядка добавьте проверку ключа или используйте СписокЗначений. Массивы структур очищайте через ТаблицуЗначений со Свернуть, а данные из базы — через РАЗЛИЧНЫЕ в запросе. Не удаляйте элементы в прямом цикле по индексу и всегда проверяйте количество и состав результата.