Разработка и Конфигурация · 12 мин
Соответствие в 1С: как создавать, заполнять и использовать
Как работать с соответствием в 1С: создание, добавление ключей, поиск значений, обход в цикле, отличия от структуры, типичные ошибки и примеры кода.
Соответствие в 1С — это встроенная коллекция, которая хранит пары «ключ — значение» и позволяет мгновенно получить значение по ключу без перебора элементов. Она нужна везде, где требуется быстрый поиск: кэширование данных справочников, подсчёт количества по категориям, сопоставление кодов из внешних систем с объектами базы, накопление итогов по произвольным признакам.
Главное преимущество соответствия перед массивом или таблицей значений — скорость поиска. Поиск по ключу выполняется за почти постоянное время независимо от числа элементов, тогда как перебор массива в поисках нужного значения замедляется пропорционально его размеру. На больших объёмах данных разница критична: обработка, которая ищет тысячи ссылок в массиве, может работать в десятки раз дольше, чем та же логика на соответствии.
Ключом соответствия может быть значение практически любого типа: строка, число, дата, ссылка на объект базы, даже другая коллекция. Значением — тоже что угодно, включая массивы, структуры и другие соответствия, что позволяет строить многоуровневые индексы. Ниже разобраны создание коллекции, основные операции, обход в цикле, отличия от структуры и типичные ошибки.
Как создать соответствие и добавить элементы
Соответствие создаётся конструктором Новый Соответствие. Коллекция изначально пустая, количество элементов ограничено только доступной памятью. Заполнение выполняется методом Вставить(Ключ, Значение) или оператором присваивания через квадратные скобки.
Кэш = Новый Соответствие;
Кэш.Вставить("АдресСервера", "srv-01.local");
Кэш.Вставить("Таймаут", 30);
// То же самое через квадратные скобки
Кэш["Активен"] = Истина;
Оба способа записи равнозначны: если ключ уже существует, значение перезаписывается, если нет — создаётся новая пара. Это удобно для накопления данных, но требует внимательности: опечатка в строковом ключе молча создаст новый элемент вместо обновления существующего, и ошибка проявится далеко от места записи.
Ключи регистрозависимы: "Код" и "код" — два разных ключа. Если данные приходят из внешних источников с непредсказуемым регистром, нормализуйте ключ перед записью и чтением, например через ВРег() или НРег().
Чтение значений и проверка существования ключа
Получить значение можно двумя способами: через квадратные скобки Соответствие[Ключ] или методом Получить(Ключ). Оба возвращают Неопределено, если ключ отсутствует. Разницы в поведении между ними нет — выбор вопрос стиля, хотя Получить() часто читается нагляднее в сложных выражениях.
Таймаут = Кэш.Получить("Таймаут");
Если Таймаут = Неопределено Тогда
Таймаут = 60; // значение по умолчанию
КонецЕсли;
Главное правило безопасной работы: никогда не используйте результат чтения без проверки, если не уверены, что ключ точно существует. Обращение к свойству или методу у Неопределено вызывает исключение и прерывает выполнение кода. Типичная защита — сравнение с Неопределено сразу после чтения.
Накопление значений по ключу
Частый сценарий — подсчёт количества или суммы по категориям. Паттерн выглядит так: прочитать текущее значение, заменить Неопределено нулём, прибавить, записать обратно.
КоличествоПоСкладам = Новый Соответствие;
Для Каждого Строка Из ТаблицаТоваров Цикл
Текущее = КоличествоПоСкладам[Строка.Склад];
Если Текущее = Неопределено Тогда
Текущее = 0;
КонецЕсли;
КоличествоПоСкладам[Строка.Склад] = Текущее + Строка.Количество;
КонецЦикла;
Обход соответствия в цикле
Соответствие обходится конструкцией Для Каждого ... Из ... Цикл. Переменная цикла имеет тип КлючИЗначение и содержит два свойства: Ключ и Значение. Это единственный способ получить одновременно и ключ, и значение при переборе.
Для Каждого Элемент Из Кэш Цикл
Сообщить(Строка(Элемент.Ключ) + " = " + Строка(Элемент.Значение));
КонецЦикла;
Порядок обхода элементов соответствия не гарантирован. Не стройте логику на предположении, что элементы вернутся в порядке добавления или по алфавиту. Если нужен упорядоченный вывод, выгрузите ключи в массив или список значений и отсортируйте их отдельно, либо используйте таблицу значений с сортировкой.
Удалять элементы прямо во время обхода циклом Для Каждого нельзя — это приводит к непредсказуемому поведению. Сначала соберите ключи для удаления в отдельный массив, а после завершения цикла пройдитесь по нему и вызовите Удалить(Ключ) для каждого.
Основные методы соответствия
Набор методов у коллекции компактный, и его достаточно для всех типовых задач. Полезно знать назначение каждого, чтобы не изобретать обходные пути.
| Метод | Назначение | Особенность |
|---|---|---|
Вставить(Ключ, Значение) | Добавить или перезаписать пару | Возвращает Истина при успехе |
Получить(Ключ) | Прочитать значение по ключу | Вернёт Неопределено, если ключа нет |
Удалить(Ключ) | Удалить пару по ключу | Не ошибка, если ключа нет |
Очистить() | Удалить все элементы | Коллекция остаётся рабочей |
Количество() | Число элементов | Для пустой коллекции — 0 |
Метод Удалить() безопасен: попытка удалить несуществующий ключ не вызывает исключения. Это упрощает код очистки — проверка существования перед удалением не нужна.
- 1Создайте соответствие: КэшСсылок = Новый Соответствие
- 2При первом обращении к коду проверьте: Ссылка = КэшСсылок[Код]
- 3Если Ссылка = Неопределено — найдите элемент запросом или методом НайтиПоКоду()
- 4Сохраните результат: КэшСсылок[Код] = Ссылка
- 5При повторном обращении ссылка вернётся из кэша без обращения к базе
Соответствие или структура: что выбрать
Структура тоже хранит пары «ключ — значение», поэтому их часто путают. Различия принципиальны и определяют выбор в каждой задаче.
Ключи структуры должны быть допустимыми идентификаторами: начинаться с буквы, не содержать пробелов и спецсимволов. Ключ соответствия — произвольное значение любого типа, включая ссылки и строки с пробелами. Если ключи приходят извне (коды контрагентов, артикулы, GUID из другой системы), подходит только соответствие.
Структура имеет метод Свойство("Имя", Значение), который проверяет наличие ключа и заодно читает значение — у соответствия такого аналога нет. Зато соответствие хранит любое число элементов, а структура ограничена по количеству свойств при создании через конструктор с перечислением ключей. Структура удобна как аналог «записи» с фиксированным набором полей, соответствие — как динамический словарь.
Сравнение вариантов
Произвольные ключи любого типа, динамическое наполнение, быстрый поиск. Нет метода проверки ключа с чтением значения за один вызов.
Ключи-идентификаторы, метод Свойство() с проверкой, удобна для фиксированного набора полей. Не подходит для ключей из внешних данных.
Нужна, когда по каждому ключу хранится несколько полей или требуется сортировка и отбор. Тяжелее и медленнее для простого поиска.
Типичные сценарии применения
На практике соответствие чаще всего встречается в нескольких устойчивых сценариях. Понимание их помогает быстро распознать, где коллекция уместна, а где лучше другой инструмент.
Первый сценарий — кэширование ссылок при загрузке данных. При обмене с внешними системами каждая строка файла содержит код или идентификатор, по которому нужно найти элемент справочника. Без кэша каждая строка порождает запрос к базе; с соответствием повторные коды обслуживаются из памяти, и загрузка большого файла ускоряется в разы.
Второй сценарий — свёртка и группировка. Подсчёт итогов по произвольному признаку (склад, контрагент, месяц) без построения запроса удобно делать накоплением в соответствии, как показано выше. Третий сценарий — сопоставление объектов при синхронизации: ключом выступает GUID или код внешней системы, значением — ссылка в текущей базе.
Проверка результата и отладка
При отладке удобнее всего смотреть содержимое соответствия через табло в конфигураторе: выделите переменную, нажмите Shift+F9 — откроется структура коллекции с ключами и значениями. В толстом клиенте содержимое разворачивается до вложенных коллекций, что позволяет проверять многоуровневые структуры.
В программной проверке опирайтесь на контрольные точки: количество элементов после заполнения должно совпадать с ожидаемым числом уникальных ключей; чтение по известному ключу должно вернуть записанное значение; чтение по заведомо отсутствующему ключу должно вернуть Неопределено, а не вызвать ошибку.
Как проверить результат
Равно числу уникальных ключей
Больше ожидаемого — вероятны дубли ключей из-за регистра или опечаток
Возвращается записанное значение
Неопределено — ключ записан иначе или не записан вовсе
Возвращается Неопределено, код продолжает работу
Исключение при обращении к значению — нет проверки после чтения
Для вывода содержимого в журнал или сообщения используйте обход циклом с конкатенацией ключа и значения. Учитывайте, что Строка() для ссылок даёт представление объекта, а для вложенных коллекций — служебное описание типа, поэтому вложенные структуры выводите рекурсивно или через отладчик.
Что важно запомнить
Соответствие — коллекция «ключ-значение» с быстрым поиском и произвольным типом ключа. Создаётся через Новый Соответствие, заполняется методом Вставить или присваиванием, читается через Получить() или скобки. Отсутствующий ключ возвращает Неопределено — всегда проверяйте результат перед использованием. Порядок обхода не гарантирован, удалять элементы внутри цикла нельзя. Для ключей из внешних данных соответствие предпочтительнее структуры.
Частые вопросы о соответствии в 1С
Можно ли использовать ссылку на объект базы как ключ соответствия?
Да, ссылки — один из самых практичных типов ключа. Сравнение ключей выполняется по значению, поэтому две переменные, содержащие ссылку на один и тот же объект, считаются одним ключом. Это удобно для накопления данных по контрагентам, складам или номенклатуре без преобразования ссылки в строку.
Чем Получить() отличается от чтения через квадратные скобки?
Функционально — ничем: оба способа возвращают значение по ключу или Неопределено при его отсутствии. Разница только в читаемости кода. В длинных выражениях метод Получить() часто нагляднее, а квадратные скобки компактнее при простых обращениях и при записи значений.
Как проверить, существует ли ключ, не читая значение?
Отдельного метода «СодержитКлюч» у соответствия нет. Стандартный приём — прочитать значение через Получить(Ключ) и сравнить с Неопределено. Ограничение подхода: если вы намеренно храните Неопределено как значение, отличить «ключа нет» от «значение равно Неопределено» невозможно — в таких случаях храните вместо Неопределено специальный маркер.
Сохраняется ли соответствие между вызовами на сервере?
Нет, если коллекция создана локально в процедуре — она живёт только в пределах вызова. Для хранения между вызовами соответствие помещают в реквизит формы (с поддержкой сериализации), в параметры сеанса через дополнительные механизмы либо пересоздают при каждом обращении. В фоновых заданиях коллекцию можно передать через параметры, если все значения сериализуемы.
Что быстрее для поиска: соответствие или таблица значений с индексом?
Для простого поиска по одному ключу соответствие обычно удобнее и не уступает по скорости. Таблица значений с индексом оправдана, когда по каждому ключу нужно хранить несколько полей, выполнять отборы по разным колонкам или сортировать результат. Выбор определяется структурой данных, а не только скоростью.
Можно ли отсортировать соответствие по ключам?
Напрямую — нет, соответствие не поддерживает сортировку, а порядок обхода не гарантирован. Обходной путь: выгрузить ключи в список значений или массив, отсортировать его, затем обходить отсортированный список и читать значения из соответствия по каждому ключу. Либо сразу использовать таблицу значений с индексом и сортировкой.