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

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

Как убрать дубли из массива в 1С

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

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

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

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

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

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

Типичные признаки того, что дубли мешают: запрос с условием «В (&Массив)» выполняется дольше обычного, в цикле по массиву один и тот же документ обрабатывается несколько раз, в итоговой выгрузке строки повторяются. Если массив используется только как параметр запроса с условием В, дубли не меняют результат, но увеличивают накладные расходы.

Массив до сотни элементовНекритично

Подойдёт любой способ, включая вложенные циклы

Тысячи элементовВажна скорость

Используйте Соответствие или ТаблицуЗначений

Элементы — ссылки и простые типыСтандартный случай

Все способы работают без ограничений

Элементы — структуры или массивыОсобый случай

Сравнение по значению затруднено, нужен ключ-строка

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

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

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

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

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

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

КонецЦикла;

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

Для Каждого КлючИЗначение Из Уникальные Цикл

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

КонецЦикла;

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

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

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

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

Способ 2. Через ТаблицуЗначений со свёрткой

Таблица значений умеет сворачивать строки методом Свернуть(), удаляя дубликаты по указанным колонкам. Способ чуть медленнее Соответствия, но нагляднее и удобен, когда дальше данные всё равно обрабатываются таблицей.

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

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

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

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

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

КонецЦикла;

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

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

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

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

Способ 3. Через запрос с группировкой

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

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

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

"ВЫБРАТЬ

| Таб.Ссылка

|ПОМЕСТИТЬ ВТ

|ИЗ

| &Таблица КАК Таб

|;

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

| ВТ.Ссылка

|ИЗ

| ВТ КАК ВТ";

Альтернатива без временной таблицы — передать массив параметром и использовать ВЫБРАТЬ РАЗЛИЧНЫЕ по источнику, отфильтрованному условием В. Но помните: передача таблицы значений параметром требует указания её структуры в тексте запроса через описание полей.

Этот способ оправдан, когда результат нужен именно выборкой, а не массивом. Гонять данные в запрос и обратно ради одного массива из десяти элементов — избыточно.

Способ 4. Вложенный цикл с поиском в результирующем массиве

Самый очевидный вариант — для каждого элемента проверять его наличие в новом массиве методом Найти(). Код простой и сохраняет порядок первых вхождений, но работает квадратично: на больших массивах становится заметно медленным.

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

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

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

Если Результат.Найти(Элемент) = Неопределено Тогда

Результат.Добавить(Элемент);

КонецЕсли;

КонецЦикла;

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

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

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

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

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

Самый быстрый на больших массивах; не сохраняет порядок, не подходит для структур

ТаблицаЗначений + Свернуть

Наглядно, удобно при дальнейшей работе с таблицей; требует описания колонок

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

Эффективен при больших объёмах и работе с БД; избыточен для маленьких массивов

Вложенный цикл с Найти()

Простой, сохраняет порядок; медленный на тысячах элементов

Особые случаи: структуры, разные регистры и неявные дубли

Массив структур

Структуры нельзя сравнивать напрямую и использовать ключом Соответствия. Решение — сформировать строковый ключ из значимых полей, например Ключ = Строка(Элемент.Контрагент) + "|" + Строка(Элемент.Договор), и дедублицировать по нему, храня сами структуры в значении Соответствия.

Строки с разным регистром

Значения «АБВ» и «абв» — разные элементы с точки зрения сравнения. Если дубли нужно искать без учёта регистра, приводите ключ к одному виду через ВРег() или НРег(), а в результат сохраняйте первое встретившееся исходное значение.

Лишние пробелы и непечатаемые символы

При загрузке из Excel или CSV дубли часто скрыты за пробелами и неразрывными пробелами. Перед дедубликацией применяйте СокрЛП(), а при необходимости — замену символов неразрывного пробела на пустую строку через СтрЗаменить().

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

После дедубликации убедитесь, что результат соответствует ожиданиям: количество элементов уменьшилось или осталось прежним, данные не потеряли тип, порядок (если важен) сохранён. Быстрая проверка — вывести ИсходныйМассив.Количество() и Результат.Количество() в консоль или сообщение.

Контрольные точки

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

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

Результат <= исходного, все уникальные значения на месте

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

Элементов больше ожидаемого или часть значений потеряна

Типы элементов
Норма

Ссылки остались ссылками, а не превратились в строки

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

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

Порядок
Норма

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

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

Порядок перемешан при требовании его сохранить

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

Как выбрать подходящий способ

Критерии выбора простые: размер массива, тип элементов, требование к порядку и контекст использования. Для большинства повседневных задач достаточно Соответствия, для интеграции с запросами — группировки на стороне СУБД.

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

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

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

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

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

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

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

Нет, у объекта Массив такого метода нет. Уникальность обеспечивают другие коллекции — Соответствие и ТаблицаЗначений, поэтому дедубликацию выполняют через них или вручную циклом.

Какой способ самый быстрый для массива из 100 000 элементов?

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

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

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

Почему Соответствие не убрало дубли из массива структур?

Каждая структура — отдельный объект, и как ключ она сравнивается по ссылке, а не по содержимому. Формируйте строковый ключ из значимых полей структуры и дедублицируйте по нему.

Нужно ли чистить массив перед передачей в параметр запроса с условием В?

На корректность результата дубли не влияют — условие В отработает одинаково. Но большой массив с повторами увеличивает накладные расходы на передачу параметра, поэтому при тысячах элементов дедубликация полезна.

Как удалить дубли в массиве строк без учёта регистра?

Приведите значения к одному регистру через ВРег() или НРег() при формировании ключа Соответствия, а в результат сохраняйте первое встретившееся исходное значение. Дополнительно примените СокрЛП(), чтобы исключить дубли из-за пробелов.