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