Коллекция Соответствие в 1С: создание, методы и применение при обмене данными
Содержание
Соответствие в 1С создают оператором Новый Соответствие — это коллекция пар «ключ — значение», где по ключу любого типа мгновенно получают связанное с ним значение. Заполняют её методом Вставить(Ключ, Значение), читают через Получить(Ключ) или квадратные скобки Соотв[Ключ], обходят циклом Для Каждого … Из … Цикл.
Чаще всего соответствие нужно, когда по одному значению надо быстро находить другое: по коду товара — ссылку на номенклатуру, по ГУИДу объекта из другой базы — ссылку в своей, по коду валюты — курс. При обмене данными между базами именно соответствие хранит сопоставление «объект источника → объект приёмника». Ниже — синтаксис, методы и рабочие примеры.
Что такое соответствие и чем оно отличается от массива
Соответствие — это универсальная коллекция встроенного языка. Внутри неё лежат пары: у каждой есть ключ и значение. Ключ уникален — двух одинаковых ключей в одной коллекции быть не может.
Главное отличие от массива: в массиве вы обращаетесь к элементу по числовому индексу (Массив[0]), а в соответствии — по ключу любого типа. Ключом может быть строка, число, дата, булево, ссылка на объект, значение перечисления.
Это даёт прямой доступ по смысловому ключу без перебора. Чтобы в массиве найти нужный элемент, вы пишете цикл и сравниваете каждый. В соответствии то же самое — одна строка Соотв.Получить(Ключ), причём скорость почти не зависит от размера коллекции.
Простой критерий выбора: нужен список по порядку — берите массив. Нужен поиск «по чему-то» — берите соответствие.
Как создать соответствие и заполнить его вручную
Пустое соответствие создаётся в одну строку:
Соотв = Новый Соответствие;
Дальше его наполняют парами. Метод Вставить принимает два параметра — ключ и значение:
КурсыВалют = Новый Соответствие;
КурсыВалют.Вставить("USD", 92.5);
КурсыВалют.Вставить("EUR", 99.8);
КурсыВалют.Вставить("CNY", 12.7);
Если вставить пару с ключом, который уже есть, старое значение заменится новым — ошибки не будет. Это удобно для накопления: можно смело перезаписывать.
Читают значение двумя способами. Через метод Получить:
Курс = КурсыВалют.Получить("USD"); // 92.5
Или через квадратные скобки — результат тот же:
Курс = КурсыВалют["EUR"]; // 99.8
Если запрошенного ключа в соответствии нет, оба варианта вернут Неопределено, а не вызовут ошибку. Это принципиальное отличие от структуры, и на нём строится большинство проверок.
Удаление пары — метод Удалить(Ключ), полная очистка — Очистить(), число пар — Количество():
КурсыВалют.Удалить("CNY");
Всего = КурсыВалют.Количество(); // 2
Перебор идёт по парам «ключ — значение». В цикле каждый элемент — это объект типа КлючИЗначение с двумя свойствами: Ключ и Значение.
Для Каждого Пара Из КурсыВалют Цикл
Сообщить(Пара.Ключ + ": " + Пара.Значение);
КонецЦикла;
Порядок обхода соответствия не гарантирован — он не совпадает с порядком вставки. Если важен порядок, сортируйте отдельно или используйте таблицу значений.
Чтобы проверить наличие ключа, сравнивают результат Получить с Неопределено:
Если КурсыВалют.Получить("GBP") = Неопределено Тогда
// такого ключа нет
КонецЦикла;
Есть тонкость: если вы специально храните в соответствии значения Неопределено, проверка Получить(Ключ) = Неопределено соврёт — она не отличит «ключа нет» от «ключ есть, но значение пустое». В таком случае проверяйте наличие через обход или храните вместо Неопределено другой маркер.
Соответствие, структура и другие коллекции: что когда применять
У встроенного языка несколько похожих коллекций, и их часто путают. Разница в типе ключа и в поведении при обращении к несуществующему элементу.
| Коллекция | Ключ / индекс | Нет элемента | Когда брать |
|---|---|---|---|
| Массив | число (индекс) | ошибка по индексу | упорядоченный перечень значений |
| Соответствие | любой тип | возвращает Неопределено | поиск значения по произвольному ключу |
| Структура | только строка-идентификатор | ошибка (нужен Свойство()) | фиксированный набор именованных полей |
| Таблица значений | строка + колонки | — | табличные данные с несколькими полями |
Ключевые выводы из таблицы:
- 📌 Структура хранит именованные поля и обращается к ним через точку (
Стр.Сумма). Ключом служит только строковый идентификатор, а запрос несуществующего поля через скобки вызывает ошибку — наличие проверяют методомСвойство(). - 📌 Соответствие принимает ключ любого типа и при отсутствии ключа молча отдаёт
Неопределено. Это делает его безопаснее для поиска. - 📌 Если на каждый ключ приходится не одно значение, а несколько полей, соответствие не подойдёт — берите таблицу значений или соответствие, где значением выступает структура.
Частый приём: значением соответствия делают структуру или другое соответствие. Так получают «двумерный» справочник — например, по ключу «склад» лежит соответствие «товар → остаток».
Как заполнить соответствие из запроса или выборки
Вручную соответствие заполняют редко. На практике его собирают из результата запроса — чтобы потом быстро находить данные без повторных обращений к базе.
Типичная задача: получить соответствие «номенклатура → остаток». Сначала запрос, затем выгрузка результата в цикл:
Запрос = Новый Запрос;
Запрос.Текст =
"ВЫБРАТЬ Номенклатура, КоличествоОстаток
|ИЗ РегистрНакопления.ТоварыНаСкладах.Остатки";
Выборка = Запрос.Выполнить().Выбрать();
ОстаткиПоТоварам = Новый Соответствие;
Пока Выборка.Следующий() Цикл
ОстаткиПоТоварам.Вставить(Выборка.Номенклатура, Выборка.КоличествоОстаток);
КонецЦикла;
После этого остаток любого товара достаётся мгновенно: ОстаткиПоТоварам[ТекущийТовар]. Это и есть главный смысл соответствия — один проход по данным, а дальше сколько угодно быстрых обращений по ключу.
Тот же шаблон применяют для кэширования ссылок: собрали соответствие «код → ссылка» один раз, и в большом цикле обработки документов не дёргаете базу на каждой строке.
Когда у ключа несколько измерений, соответствие вкладывают одно в другое. Остаток по паре «склад + товар» удобно хранить как соответствие складов, в котором значением лежит соответствие товаров:
Остатки = Новый Соответствие;
Пока Выборка.Следующий() Цикл
ПоТоварам = Остатки.Получить(Выборка.Склад);
Если ПоТоварам = Неопределено Тогда
ПоТоварам = Новый Соответствие;
Остатки.Вставить(Выборка.Склад, ПоТоварам);
КонецЕсли;
ПоТоварам.Вставить(Выборка.Номенклатура, Выборка.КоличествоОстаток);
КонецЦикла;
Теперь остаток достаётся по двум ключам: сначала берут вложенное соответствие по складу, затем значение по товару.
ПоСкладу = Остатки.Получить(ТекущийСклад);
Остаток = ?(ПоСкладу = Неопределено, 0, ПоСкладу.Получить(ТекущийТовар));
Проверка на Неопределено на каждом уровне обязательна: если склад в данных не встретился, вложенного соответствия не будет, и прямое обращение к нему оборвёт код.
Как соответствие используют при обмене данными между базами
В выгрузках и загрузках соответствие решает центральную задачу обмена — сопоставление объектов источника и приёмника. У объекта в одной базе своя ссылка, в другой — своя. Чтобы при повторной загрузке не плодить дубли, нужно знать, какому объекту-источнику какой объект уже соответствует.
Как это устроено на практике:
- При загрузке объект ищут по уникальному признаку — коду, ИНН, артикулу или ГУИДу (
УникальныйИдентификаторссылки). - Найденную или вновь созданную ссылку кладут в соответствие: ключ — идентификатор из источника, значение — ссылка в своей базе.
- Когда в выгрузке встречается ссылка на этот же объект (например, товар в табличной части документа), его ссылку в приёмнике берут прямо из соответствия, а не ищут в базе заново.
СопоставлениеОбъектов = Новый Соответствие;
// при обработке объекта-источника
СсылкаПриёмника = НайтиИлиСоздать(ОбъектИсточника);
СопоставлениеОбъектов.Вставить(ОбъектИсточника.Идентификатор, СсылкаПриёмника);
Ключ при сопоставлении по ГУИДу удобнее хранить строкой. Уникальный идентификатор ссылки получают методом УникальныйИдентификатор(), а в ключ кладут его строковое представление — так ключ из источника и ключ при поиске заведомо одного типа:
КлючИсточника = Строка(ОбъектИсточника.Ссылка.УникальныйИдентификатор());
СопоставлениеОбъектов.Вставить(КлючИсточника, СсылкаПриёмника);
Если в одном месте положить ключом сам идентификатор (тип УникальныйИдентификатор), а искать по строке, соответствие их не свяжет — вернётся Неопределено. Одинаковый тип ключа на запись и на чтение здесь критичен.
Если обмен идёт порциями или в несколько проходов, соответствие, собранное в памяти, живёт только внутри одного вызова. Долговременное сопоставление между сеансами хранят в регистре сведений или в самих ссылках плана обмена, а соответствие используют как быстрый кэш внутри одной обработки.
В типовых механизмах (планы обмена, правила конвертации) сопоставление объектов платформа ведёт сама. Соответствие в собственном коде пишут там, где обмен нестандартный: разовая загрузка из файла, интеграция с внешней системой через код, перенос данных обработкой.
Частые ошибки при работе с соответствием
Разберём, что идёт не так и как чинить. Проблемы почти всегда в типе ключа или в предположении, что ключ точно есть.
Как посмотреть содержимое соответствия при отладке
Увидеть, что реально лежит в коллекции, помогает отладчик. Поставьте точку останова и наведите курсор на переменную — во всплывающей подсказке или в окне «Табло» соответствие раскрывается по парам ключ — значение.
Быстрый способ без отладчика — вывести пары в сообщения:
Для Каждого Пара Из Соотв Цикл
Сообщить("" + Пара.Ключ + " = " + Пара.Значение);
КонецЦикла;
Если нужно только убедиться, что коллекция не пустая, достаточно Соотв.Количество(). Ноль означает, что цикл заполнения не отработал или запрос вернул пусто — проверяйте источник данных, а не само соответствие.
Когда значением соответствия служит структура или ещё одно соответствие, в «Табло» разворачивайте вложенный узел — платформа покажет всю иерархию.
Когда пригодится фиксированное соответствие
Если коллекцию нужно только читать и защитить от случайного изменения, используют неизменяемый вариант — ФиксированноеСоответствие. Его создают на основе обычного:
Справочник = Новый ФиксированноеСоответствие(Соотв);
После этого методы Вставить и Удалить недоступны — попытка изменить вызовет ошибку. Читается фиксированное соответствие точно так же: Справочник[Ключ], Справочник.Получить(Ключ), обход циклом.
Такой вариант передают в параметры формы, в структуру настроек, в кэш общих модулей — везде, где значение должно оставаться неизменным на всё время жизни.
Частые вопросы
Чем соответствие отличается от структуры простыми словами?
Неопределено. Структура — для фиксированного набора именованных полей, соответствие — для поиска по произвольному ключу.Можно ли использовать ссылку на объект как ключ?
Сохраняется ли порядок добавления пар?
Как превратить соответствие в таблицу значений?
Добавить(). После этого таблицу можно сортировать и отбирать.