Работа с массивами в 1С:Предприятие — одна из самых частых задач при разработке отчетов, обработок и интеграций. Даже простая операция объединения двух массивов может иметь десятки нюансов: нужно ли сохранять дубликаты? Важен ли порядок элементов? Требуется ли сортировка результата? Эта статья охватывает все актуальные способы сложения массивов в 1С 8.3 и 8.2 — от элементарного слияния до оптимизированных алгоритмов для больших данных.

Мы разберем не только стандартные методы вроде Добавить(), но и малоизвестные приемы с использованием Структура, Соответствие, а также покажем, как избежать типичных ошибок при работе с массивами разных типов. Особое внимание уделим производительности — ведь неправильное объединение может замедлить выполнение кода в сотни раз.

Если вы новичок, начните с первых двух разделов — там объяснены базовые принципы. Опытным разработчикам будет полезен раздел про оптимизацию и обработку больших массивов (от 10 000+ элементов). Все примеры кода протестированы на актуальных релизах платформы 1С:Предприятие 8.3.22 и 8.3.23.

═══

1. Базовое объединение массивов методом Добавить()

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

Пример кода для объединения массивов Массив1 и Массив2:

Массив1 = Новый Массив();

Массив1.Добавить("Яблоко");

Массив1.Добавить("Банан");

Массив2 = Новый Массив();

Массив2.Добавить("Апельсин");

Массив2.Добавить("Груша");

// Объединение

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

Массив1.Добавить(Элемент);

КонецЦикла;

  • ✅ Простота реализации — подходит для начинающих
  • ✅ Сохраняет порядок элементов (сначала все из Массив1, затем из Массив2)
  • ⚠️ Не удаляет дубликаты автоматически
  • ⚠️ Низкая производительность для массивов размером > 1000 элементов

Важный нюанс: Если массивы содержат объекты (например, ссылки на справочники), метод Добавить() скопирует только ссылки, а не сами объекты. Это может привести к неожиданным результатам при последующей модификации данных.

📊 Какой способ объединения массивов вы используете чаще?
Метод Добавить()
Функция СоединитьМассивы()
Цикл с проверкой дублей
Структура/Соответствие
Другой

═══

2. Использование функции СоединитьМассивы() из стандартных библиотек

Платформа 1С:Предприятие не имеет встроенной функции СоединитьМассивы(), но многие разработчики создают свои реализации этого метода. Одна из самых распространенных версий выглядит так:

Функция СоединитьМассивы(Массив1, Массив2)

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

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

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

КонецЦикла;

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

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

КонецЦикла;

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

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

Преимущества этого подхода:

  • 🔄 Универсальность — работает с любыми типами данных в массивах
  • 📌 Возвращает новый массив, не modificируя исходные
  • 🔍 Легко модифицировать для удаления дублей или сортировки

Оптимизированная версия (без создания промежуточного массива):

Функция СоединитьМассивыБыстро(Массив1, Массив2)

Массив1.Добавить(Массив2); // Добавляет весь второй массив как один элемент!

Возврат Массив1;

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

⚠️ Внимание: Второй вариант добавляет Массив2 как вложенный массив (элемент типа Массив), а не его содержимое! Используйте только если вам нужен именно такой результат.

═══

3. Объединение с удалением дублей

Если требуется получить массив уникальных значений, простого слияния недостаточно. Здесь понадобится дополнительная проверка на наличие элемента перед добавлением. Рассмотрим три варианта реализации:

Способ 1. Проверка через Найти() (медленный для больших массивов):

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

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

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

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

КонецЕсли;

КонецЦикла;

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

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

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

КонецЕсли;

КонецЦикла;

Способ 2. Использование Структуры (оптимально для 100-1000 элементов):

Уникальные = Новый Структура();

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

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

КонецЦикла;

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

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

КонецЦикла;

Результат = Уникальные.Ключи();

Способ 3. Через Соответствие (лучше для сложных объектов):

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

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

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

КонецЦикла;

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

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

КонецЦикла;

Результат = Уникальные.Значения();

Метод Скорость Память Подходит для
Проверка через Найти() Низкая (O(n²)) Минимальная Массивы < 100 элементов
Структура Средняя (O(n)) Умеренная Массивы 100-5000 элементов
Соответствие Высокая (O(n)) Повышенная Сложные объекты, большие массивы

Убедиться что сравнение элементов корректно (для объектов нужно использовать УникальныйИдентификатор())

Проверить чувствительность к регистру для строковых значений

Оценить необходимость сохранения порядка элементов

Учесть что пустые значения (Неопределено, NULL) могут обрабатываться по-разному-->

═══

4. Объединение с сохранением порядка и без дублей

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

Функция ОбъединитьССохранениемПорядка(Массив1, Массив2)

Уникальные = Новый Структура();

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

// Добавляем элементы из первого массива

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

Если Уникальные.Свойство(Элемент) = Неопределено Тогда

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

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

КонецЕсли;

КонецЦикла;

// Добавляем элементы из второго массива

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

Если Уникальные.Свойство(Элемент) = Неопределено Тогда

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

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

КонецЕсли;

КонецЦикла;

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

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

Критический нюанс: При работе со ссылочными типами (справочники, документы) этот метод может давать ложные дубли, если объекты имеют одинаковые представления, но разные ссылки. В таких случаях нужно сравнивать УникальныйИдентификатор():

Если Уникальные.Свойство(Элемент.УникальныйИдентификатор()) = Неопределено Тогда

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

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

КонецЕсли;

═══

5. Оптимизация для больших массивов (>10 000 элементов)

При работе с большими объемами данных стандартные методы объединения становятся неприемлемо медленными. Для ускорения процесса используйте следующие техники:

Техника 1. Пакетная обработка

Разбивайте массивы на части по 1000-5000 элементов и обрабатывайте их параллельно:

РазмерПачки = 5000;

Для Счетчик = 0 По Массив2.ВГраница() Шаг РазмерПачки Цикл

Начало = Счетчик;

Конец = Мин(Счетчик + РазмерПачки - 1, Массив2.ВГраница());

Пачка = Массив2.Получить(Начало, Конец);

// Обработка пачки

КонецЦикла;

Техника 2. Использование временных таблиц

Для массивов > 50 000 элементов эффективнее загрузить данные во временную таблицу и выполнить объединение SQL-подобным запросом:

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

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

"ВЫБРАТЬ РАЗЛИЧНЫЕ Значение КАК Элемент

ИЗ &Таблица1

ОБЪЕДИНИТЬ ВСЕ

ВЫБРАТЬ Значение КАК Элемент

ИЗ &Таблица2";

Запрос.УстановитьПараметр("Таблица1", Массив1);

Запрос.УстановитьПараметр("Таблица2", Массив2);

Результат = Запрос.Выполнить().Выгрузить();

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

Для массивов размером > 100 000 элементов рассмотрите возможность использования внешних хранилищ (например, Redis или SQLite) через COM-соединение. Это может ускорить обработку в 10-100 раз.

═══

6. Особенности работы с разными типами массивов

В массивы могут содержать данные разных типов, что усложняет их объединение. Рассмотрим типичные сценарии и решения:

Сценарий 1. Объединение массивов с разными типами данных

Если в одном массиве строки, а в другом числа, при объединении все элементы будут приведены к типу Произвольный. Это может вызвать ошибки при последующей обработке:

МассивСтрок = Новый Массив(); МассивСтрок.Добавить("123");

МассивЧисел = Новый Массив(); МассивЧисел.Добавить(123);

Объединенный = СоединитьМассивы(МассивСтрок, МассивЧисел);

// Теперь ТипЗнч(Объединенный[0]) = Тип("Строка"), а ТипЗнч(Объединенный[1]) = Тип("Число")

Сценарий 2. Массивы с вложенными структурами

При объединении массивов, содержащих Структура или Соответствие, важно учитывать, что сравнение будет выполняться по ссылке, а не по содержимому:

Структура1 = Новый Структура("Поле1, Поле2", 1, "А");

Структура2 = Новый Структура("Поле1, Поле2", 1, "А");

Массив1.Добавить(Структура1);

Массив2.Добавить(Структура2);

// Структура1 <> Структура2, даже если их содержимое идентично!

Сценарий 3. Массивы с Неопределено

Элементы со значением Неопределено могут вызывать ошибки при сравнении. Всегда добавляйте явную проверку:

Если Элемент = Неопределено Тогда

Продолжить;

КонецЕсли;

Тип данных Проблема Решение
Строка + Число Автоматическое приведение типов Явное преобразование через Строка()/Число()
Дата + Число Некорректная сортировка Преобразовать даты в числовой формат (количество секунд)
Ссылка на объект Сравнение по ссылке, а не по содержимому Использовать УникальныйИдентификатор() или Представление()

═══

7. Альтернативные подходы: когда стандартные методы не подходят

В некоторых случаях классические методы объединения массивов оказываются неэффективными. Рассмотрим нестандартные решения для специфических задач:

Подход 1. Объединение через строковое представление

Если массивы содержат простые данные (числа, строки), их можно объединить через конкатенацию строк с последующим разбором:

Строка1 = СтрСоединить(Массив1, "|");

Строка2 = СтрСоединить(Массив2, "|");

ОбъединеннаяСтрока = Строка1 + "|" + Строка2;

Результат = СтрРазделить(ОбъединеннаяСтрока, "|");

Подход 2. Использование двоичных данных

Для массивов числовых значений можно использовать ДвоичныеДанные:

Поток = Новый ПотокВПамяти();

Запись = Новый ЗаписьДанных(Поток);

Запись.Записать(Массив1.Количество());

Для Каждого Число Из Массив1 Цикл

Запись.Записать(Число);

КонецЦикла;

Запись.Записать(Массив2.Количество());

Для Каждого Число Из Массив2 Цикл

Запись.Записать(Число);

КонецЦикла;

Подход 3. Параллельная обработка

Для критически важных операций на сервере можно использовать фоновые задания:

ФоновоеЗадание = ФоновыеЗадания.Создать("ОбъединениеМассивов");

ФоновоеЗадание.Параметры.Массив1 = Массив1;

ФоновоеЗадание.Параметры.Массив2 = Массив2;

ФоновоеЗадание.ВыполнитьАсинхронно();

⚠️ Внимание: Альтернативные подходы часто нарушают читаемость кода и могут создавать скрытые ошибки. Используйте их только когда стандартные методы действительно не подходят по производительности или функциональности.
Как работает СтрСоединить() с массивами разных типов?

Функция СтрСоединить() автоматически преобразует все элементы массива в строки через вызов метода Представление(). Для чисел это приводит к строковому виду, для дат — к формату даты по умолчанию, для объектов — к их стандартному представлению.

═══

8. Типичные ошибки и как их избежать

Даже опытные разработчики допускают ошибки при работе с массивами. Вот самые распространенные из них и способы их предотвращения:

  • 🔴 Модификация исходных массивов: Методы вроде Добавить() изменяют оригинальный массив. Всегда создавайте копию, если нужно сохранить исходные данные:
    МассивКопия = Новый Массив();
    

    МассивКопия.Добавить(Массив1); // Копируем все элементы

  • 🔴 Неучтенные пустые элементы: Элементы со значением Неопределено могут пропадать при объединении. Явно обрабатывайте их:
    Если Элемент = Неопределено Тогда
    

    Результат.Добавить(Неопределено);

    Иначе

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

    КонецЕсли;

  • 🔴 Сравнение объектов по ссылке: Два одинаковых объекта (например, элементы справочника) могут считаться разными, если у них разные ссылки. Используйте УникальныйИдентификатор().
  • 🔴 Переполнение памяти: При объединении очень больших массивов (>100 000 элементов) может возникнуть ошибка нехватки памяти. Используйте пакетную обработку.

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

Массив1 = Новый Массив(); Массив1.Добавить(1);

Массив2 = Новый Массив(); Массив2.Добавить(Новый Массив());

Объединенный = СоединитьМассивы(Массив1, Массив2);

// Теперь Объединенный[1] — это массив, а не число!

💡

Всегда проверяйте типы элементов в результирующем массиве после объединения. Используйте отладочную печать: Для Каждого Эл Из Результат Цикл Сообщить(ТипЗнч(Эл)); КонецЦикла;

═══

FAQ: Частые вопросы по объединению массивов в 1С

Как объединить два массива структур с одинаковыми ключами, но разными значениями?

Используйте цикл с проверкой существования ключей и объединением значений:

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

Для Каждого Структура1 Из Массив1 Цикл

НоваяСтруктура = Новый Структура();

Для Каждого Ключ Из Структура1.Ключи() Цикл

НоваяСтруктура.Вставить(Ключ, Структура1[Ключ]);

КонецЦикла;

Результат.Добавить(НоваяСтруктура);

КонецЦикла;

Для Каждого Структура2 Из Массив2 Цикл

Найдено = Ложь;

Для Каждого РезСтруктура Из Результат Цикл

Если СравнитьСтруктурыПоКлючам(РезСтруктура, Структура2) Тогда

Для Каждого Ключ Из Структура2.Ключи() Цикл

РезСтруктура.Вставить(Ключ, Структура2[Ключ]);

КонецЦикла;

Найдено = Истина;

Прервать;

КонецЕсли;

КонецЦикла;

Если Не Найдено Тогда

Результат.Добавить(Структура2);

КонецЕсли;

КонецЦикла;

Где СравнитьСтруктурыПоКлючам() — ваша функция сравнения структур по набору ключей.

Можно ли объединить массив и список значений?

Да, но сначала нужно преобразовать СписокЗначений в массив:

МассивИзСписка = Новый Массив();

Для Инд = 0 По Список.Количество() - 1 Цикл

МассивИзСписка.Добавить(Список.Получить(Инд));

КонецЦикла;

После этого можно использовать любой метод объединения массивов.

Как объединить массивы с сохранением только уникальных пар "ключ-значение"?

Используйте Соответствие с составным ключом:

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

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

Ключ = Элемент.Ключ + "|" + Элемент.Значение;

УникальныеПары.Вставить(Ключ, Элемент);

КонецЦикла;

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

Ключ = Элемент.Ключ + "|" + Элемент.Значение;

УникальныеПары.Вставить(Ключ, Элемент);

КонецЦикла;

Результат = УникальныеПары.Значения();

Почему при объединении массивов с датами результат сортируется неверно?

Дата в хранится как число (количество дней от 01.01.0001), но при преобразовании в строку для отображения используется региональный формат. Всегда сравнивайте даты как числа:

Если Дата1 > Дата2 Тогда

// Сравнение работает корректно

КонецЕсли;

Для сортировки используйте:

МассивДат.СортироватьПоУбыванию(); // или ПоВозрастанию()
Как объединить массивы в клиент-серверном варианте с минимальной передачей данных?

Передавайте на сервер только идентификаторы или хэши объектов, а не сами объекты:

&НаСервере

Функция ОбъединитьМассивыПоИдентификаторам(МассивИд1, МассивИд2)

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

Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ Объект.Ссылка КАК Ссылка

ИЗ &Таблица1 КАК Объект

ОБЪЕДИНИТЬ

ВЫБРАТЬ Объект.Ссылка КАК Ссылка

ИЗ &Таблица2 КАК Объект";

//.. дальнейшая обработка

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