Разработка и Конфигурация · 11 мин
Как объединить два списка значений в 1С
Как объединить два списка значений в 1С: методы Добавить, ЗагрузитьЗначения, работа через массив, удаление дублей. Примеры кода, ошибки и проверка результата.
Объединение двух списков значений — частая задача при разработке на встроенном языке 1С: например, когда нужно собрать в один список выбранные пользователем элементы из двух форм, склеить результаты двух запросов или объединить настройки отбора. Объект СписокЗначений имеет ограниченный набор методов, и прямого метода «объединить» у него нет, поэтому задачу решают несколькими обходными путями.
Выбор способа зависит от трёх условий: нужно ли сохранить представления и пометки элементов, допустимы ли дубликаты значений и насколько велик объём данных. Ниже разобраны рабочие варианты с примерами кода, критериями выбора и типичными ошибками.
Что нужно знать о списке значений перед объединением
Объект СписокЗначений хранит не только сами значения, но и представление (строку, которую видит пользователь), пометку (флажок) и картинку элемента. При объединении важно решить, переносить ли эти дополнительные данные или достаточно самих значений.
Второй момент — дубликаты. Список значений допускает повторяющиеся значения: метод Добавить() не проверяет уникальность. Если вы объединяете два списка, где встречаются одинаковые элементы, в результате появятся дубли, и их придётся удалять отдельно.
Третий нюанс — типы данных. Список может хранить значения разных типов, но если дальше список используется в параметре запроса или в отборе, смешение типов (например, ссылки разных справочников и строки) может привести к ошибкам или неожиданному поведению.
Способ 1. Объединение циклом через метод Добавить()
Самый универсальный вариант — перебрать элементы второго списка и добавить их в первый. Так сохраняются значения, представления и пометки, а порядок элементов остаётся предсказуемым: сначала элементы первого списка, затем второго.
Для Каждого Элемент Из Список2 Цикл
Список1.Добавить(Элемент.Значение, Элемент.Представление, Элемент.Пометка);
КонецЦикла;
Метод Добавить() принимает параметры: значение, представление (необязательно), пометка (необязательно), картинка (необязательно). Если представление не указать, оно сформируется автоматически из значения — для ссылочных типов это обычно приемлемо, но для составных случаев лучше переносить представление явно.
Если первый список нужно оставить без изменений, создайте третий список и скопируйте в него оба исходных. Это безопаснее, когда исходные списки связаны с реквизитами формы или используются дальше в алгоритме.
СписокИтог = Новый СписокЗначений;
Для Каждого Элемент Из Список1 Цикл
СписокИтог.Добавить(Элемент.Значение, Элемент.Представление, Элемент.Пометка);
КонецЦикла;
Для Каждого Элемент Из Список2 Цикл
СписокИтог.Добавить(Элемент.Значение, Элемент.Представление, Элемент.Пометка);
КонецЦикла;Способ 2. Объединение через массивы и ЗагрузитьЗначения()
Когда представления и пометки не нужны, удобнее работать через массивы. Метод ВыгрузитьЗначения() возвращает массив значений списка, а ЗагрузитьЗначения() заполняет список из массива, предварительно очищая его.
Массив1 = Список1.ВыгрузитьЗначения();
Массив2 = Список2.ВыгрузитьЗначения();
Для Каждого Значение Из Массив2 Цикл
Массив1.Добавить(Значение);
КонецЦикла;
СписокИтог = Новый СписокЗначений;
СписокИтог.ЗагрузитьЗначения(Массив1);
У этого подхода два ограничения. Во-первых, теряются представления и пометки — список будет содержать только значения. Во-вторых, ЗагрузитьЗначения() сначала очищает список, поэтому нельзя загружать массив в тот же список, из которого он был выгружен, без промежуточного массива — данные будут потеряны.
Способ через массивы удобен, когда дальше значения передаются в запрос как параметр: запросу всё равно нужен массив или список значений без представлений, и промежуточный массив можно использовать напрямую.
Способ 3. Объединение без дубликатов
Частая потребность — получить объединение, где каждое значение встречается один раз (аналог операции «ИЛИ» для множеств). Простейший вариант — проверять наличие значения перед добавлением методом НайтиПоЗначению():
Для Каждого Элемент Из Список2 Цикл
Если Список1.НайтиПоЗначению(Элемент.Значение) = Неопределено Тогда
Список1.Добавить(Элемент.Значение, Элемент.Представление, Элемент.Пометка);
КонецЕсли;
КонецЦикла;
У этого подхода есть ограничение по производительности: НайтиПоЗначению() выполняет линейный поиск, и на больших списках (тысячи элементов) объединение замедлится. Для крупных объёмов эффективнее выгрузить всё в таблицу значений и свернуть:
Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Значение");
Для Каждого Элемент Из МассивОбщий Цикл
Строка = Таблица.Добавить();
Строка.Значение = Элемент;
КонецЦикла;
Таблица.Свернуть("Значение");
СписокИтог.ЗагрузитьЗначения(Таблица.ВыгрузитьКолонку("Значение"));
Альтернатива — использовать Соответствие как промежуточное хранилище: ключи соответствия уникальны, поэтому дубликаты отсеиваются автоматически при вставке.
Сравнение способов объединения
Сохраняет представления и пометки, простой и читаемый. Не убирает дубликаты, при проверке уникальности медленный на больших списках.
Короткий код, удобно для передачи в запрос. Теряются представления и пометки, дубликаты сохраняются.
Быстро убирает дубликаты на больших объёмах. Кода больше, представления теряются.
Автоматическая уникальность ключей, быстрый поиск. Требуется дополнительный перенос в список.
Как выбрать подходящий способ
Ориентируйтесь на три вопроса. Первый: нужны ли представления и пометки в итоговом списке? Если да — только цикл с Добавить(). Второй: допустимы ли дубликаты? Если нет — добавьте проверку НайтиПоЗначению() или используйте свёртку таблицы. Третий: каков объём данных? До нескольких сотен элементов разница в способах незаметна, при тысячах — выбирайте таблицу значений или соответствие.
Отдельный случай — объединение списков в запросе. Если оба набора значений формируются запросами к базе, зачастую правильнее объединить их на уровне запроса через ОБЪЕДИНИТЬ или ОБЪЕДИНИТЬ ВСЕ, а не собирать списки в коде. Это быстрее и сразу даёт уникальность (при ОБЪЕДИНИТЬ без ВСЕ).
Как выбрать действие
Проверка результата объединения
После объединения убедитесь, что результат соответствует ожиданиям. Минимальная проверка — количество элементов: при объединении без удаления дублей итоговое количество должно равняться сумме размеров исходных списков. Если оно меньше — где-то срабатывает отсечение дублей; если больше — вероятно, цикл выполняется лишний раз.
Для отладки выведите содержимое списка в цикле через Сообщить() или посмотрите его в табло отладчика. Проверьте также типы значений: если в итоговом списке оказались строки вместо ссылок, значит где-то в цепочке значение было преобразовано, например при сериализации или передаче между клиентом и сервером.
Как проверить результат
Равно сумме размеров исходных списков (без удаления дублей)
Меньше или больше ожидаемого — проверьте логику цикла и свёртку
Сохранены исходные типы (ссылки, числа и т.д.)
Значения превратились в строки или Неопределено
Совпадают с исходными представлениями
Представления пустые или сформированы автоматически там, где нужны исходные
Соответствует задуманному: есть или отсутствуют
Дубли появились там, где должна быть уникальность
Типичные ошибки и ограничения
Самая частая ошибка — попытка загрузить значения в тот же список, из которого они выгружены: Список1.ЗагрузитьЗначения(Список1.ВыгрузитьЗначения()) без промежуточного массива в сложной логике приводит к потере данных, потому что ЗагрузитьЗначения() сначала очищает список.
Вторая ошибка — модификация списка во время перебора его же элементов. Если вы перебираете Список1 и добавляете элементы в него же, цикл может стать бесконечным или пропустить элементы. Всегда добавляйте элементы в другой список либо перебирайте копию.
Третья группа проблем связана с передачей списков между клиентом и сервером в управляемых формах. Список значений сериализуется, и ссылочные значения при некоторых сценариях могут терять связь с контекстом. Если объединение выполняется в клиент-серверном коде, надёжнее выполнять его целиком на сервере.
Частые вопросы
Можно ли объединить два списка значений одной командой?
Нет, у объекта СписокЗначений нет метода объединения. Ближайшие по смыслу операции — Добавить() для отдельных элементов и ЗагрузитьЗначения() для загрузки массива. Объединение всегда реализуется циклом или через промежуточную коллекцию (массив, таблицу значений, соответствие).
Как объединить списки, чтобы порядок элементов сохранился?
Используйте последовательное добавление: сначала все элементы первого списка, затем второго. Список значений хранит элементы в порядке добавления, пока вы не примените СортироватьПоЗначению() или СортироватьПоПредставлению().
Чем отличается ОБЪЕДИНИТЬ от ОБЪЕДИНИТЬ ВСЕ в запросе?
ОБЪЕДИНИТЬ убирает дубликаты строк из результата, ОБЪЕДИНИТЬ ВСЕ сохраняет все строки, включая повторы. Если оба набора данных получаются запросами, объединение на уровне запроса обычно эффективнее, чем сборка списков в коде.
Как удалить дубликаты из уже объединённого списка?
Выгрузите значения в таблицу значений с одной колонкой, выполните Свернуть() по этой колонке и загрузите результат обратно через ЗагрузитьЗначения(). Для небольших списков можно пройти циклом с конца и удалять элементы, которые уже встречались, проверяя НайтиПоЗначению().
Почему после объединения пропали представления элементов?
Представления теряются при использовании ВыгрузитьЗначения() и ЗагрузитьЗначения() — эти методы работают только со значениями. Чтобы сохранить представления, переносите элементы циклом через Добавить() с явной передачей параметра Представление.
Можно ли объединить списки значений разных типов?
Технически да — список значений допускает элементы разных типов. Но если итоговый список будет использоваться в отборе или параметре запроса, смешение типов может вызвать ошибки. Перед объединением приведите значения к ожидаемому типу или проверяйте тип каждого элемента.
Что важно запомнить
Прямого метода объединения у СписокЗначений нет: используйте цикл с Добавить() для сохранения представлений, массивы и ЗагрузитьЗначения() — когда нужны только значения, а таблицу значений со свёрткой — для удаления дублей на больших объёмах. Не модифицируйте список во время его перебора и проверяйте итоговое количество элементов и типы значений.