Работа с массивами в 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);
Результат = Запрос.Выполнить().Выгрузить();
⚠️ Внимание: При использовании временных таблиц убедитесь, что в массивах нет рекурсивных ссылок на объекты 1С — это может привести к ошибке сериализации. Для сложных объектов предварительно преобразуйте их в строки или числовые идентификаторы.
Для массивов размером > 100 000 элементов рассмотрите возможность использования внешних хранилищ (например, Redis или SQLite) через COM-соединение. Это может ускорить обработку в 10-100 раз.
═══
6. Особенности работы с разными типами массивов
В 1С массивы могут содержать данные разных типов, что усложняет их объединение. Рассмотрим типичные сценарии и решения:
Сценарий 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 = Массив1;
ФоновоеЗадание.Параметры.Массив2 = Массив2;
ФоновоеЗадание.ВыполнитьАсинхронно();
⚠️ Внимание: Альтернативные подходы часто нарушают читаемость кода и могут создавать скрытые ошибки. Используйте их только когда стандартные методы действительно не подходят по производительности или функциональности.
Как работает СтрСоединить() с массивами разных типов?
Функция СтрСоединить() автоматически преобразует все элементы массива в строки через вызов метода Представление(). Для чисел это приводит к строковому виду, для дат — к формату даты по умолчанию, для объектов — к их стандартному представлению.
═══
8. Типичные ошибки и как их избежать
Даже опытные разработчики 1С допускают ошибки при работе с массивами. Вот самые распространенные из них и способы их предотвращения:
- 🔴 Модификация исходных массивов: Методы вроде
Добавить()изменяют оригинальный массив. Всегда создавайте копию, если нужно сохранить исходные данные:МассивКопия = Новый Массив();МассивКопия.Добавить(Массив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 Цикл
Ключ = Элемент.Ключ + "|" + Элемент.Значение;
УникальныеПары.Вставить(Ключ, Элемент);
КонецЦикла;
Результат = УникальныеПары.Значения();
Почему при объединении массивов с датами результат сортируется неверно?
Дата в 1С хранится как число (количество дней от 01.01.0001), но при преобразовании в строку для отображения используется региональный формат. Всегда сравнивайте даты как числа:
Если Дата1 > Дата2 Тогда
// Сравнение работает корректно
КонецЕсли;
Для сортировки используйте:
МассивДат.СортироватьПоУбыванию(); // или ПоВозрастанию()
Как объединить массивы в клиент-серверном варианте с минимальной передачей данных?
Передавайте на сервер только идентификаторы или хэши объектов, а не сами объекты:
&НаСервере
Функция ОбъединитьМассивыПоИдентификаторам(МассивИд1, МассивИд2)
Запрос = Новый Запрос;
Запрос.Текст = "ВЫБРАТЬ РАЗЛИЧНЫЕ Объект.Ссылка КАК Ссылка
ИЗ &Таблица1 КАК Объект
ОБЪЕДИНИТЬ
ВЫБРАТЬ Объект.Ссылка КАК Ссылка
ИЗ &Таблица2 КАК Объект";
//.. дальнейшая обработка
КонецФункции