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