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