К статье
Практический материал

Разработка и Конфигурация · 9 мин

Как в 1С получить ключ соответствия

Как в 1С получить ключ соответствия: перебор через Для каждого, проверка наличия ключа, получение значения по ключу. Примеры кода, ошибки и FAQ.

Объект «Соответствие» в языке 1С хранит пары «ключ — значение», при этом прямого метода «получить список ключей» у него нет. Поэтому вопрос, как получить ключ соответствия, возникает у разработчиков регулярно: нужно перебрать все ключи, проверить существование конкретного ключа или найти ключ по значению. Каждая из этих задач решается своим приёмом.

Базовый инструмент — конструкция «Для каждого … Из … Цикл», которая возвращает элементы типа «КлючИЗначение». У каждого элемента доступны свойства «Ключ» и «Значение», через которые и выполняется вся работа. Ниже разобраны рабочие приёмы с примерами кода, типичными ошибками и способами проверки результата.

Важно понимать ограничение платформы: соответствие не гарантирует порядок обхода элементов. Если логика зависит от порядка ключей, используйте «Структуру», список значений или таблицу значений — иначе поведение кода будет непредсказуемым.

Что такое соответствие и как устроен ключ

Соответствие — это коллекция пар «ключ — значение», где ключ может быть практически любого типа: строка, число, ссылка на объект базы, дата и даже Неопределено. Значение — тоже произвольного типа, включая другие коллекции. Именно типизированный ключ отличает соответствие от структуры, где ключом может быть только строка-идентификатор.

Ключи в соответствии уникальны: при вставке пары с уже существующим ключом старое значение заменяется новым без предупреждения. Это частая причина «потери» данных — разработчик считает, что добавил две записи, а фактически перезаписал одну.

Перебор всех ключей через «Для каждого»

Основной способ получить ключи соответствия — цикл по элементам коллекции. Каждая итерация возвращает объект «КлючИЗначение», у которого читаем свойство «Ключ»:

Для каждого КлючИЗначение Из МоеСоответствие Цикл

Сообщить(КлючИЗначение.Ключ);

КонецЦикла;

Если нужно собрать ключи в отдельный массив для дальнейшей обработки, заполняйте его внутри цикла:

МассивКлючей = Новый Массив;

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

МассивКлючей.Добавить(Элемент.Ключ);

КонецЦикла;

Порядок обхода не определён и может меняться между вызовами, особенно при передаче соответствия между клиентом и сервером. Если нужен отсортированный список ключей, соберите их в массив и отсортируйте отдельно либо используйте список значений с сортировкой.

bsl
Для каждого КлючИЗначение Из МоеСоответствие Цикл
    ТекущийКлюч = КлючИЗначение.Ключ;
    ТекущееЗначение = КлючИЗначение.Значение;
КонецЦикла;

Проверка существования конкретного ключа

Чтобы узнать, есть ли ключ в соответствии, используют метод Получить(). Он возвращает значение по ключу или Неопределено, если ключ не найден:

Результат = МоеСоответствие.Получить(ИскомыйКлюч);

Если Результат = Неопределено Тогда

// Ключа нет, либо по нему хранится Неопределено

КонецЕсли;

Тонкость в том, что Неопределено возвращается и когда ключ отсутствует, и когда по ключу реально записано Неопределено. Если такая ситуация возможна в вашей логике, надёжнее проверять через перебор со сравнением ключа либо не хранить Неопределено в качестве значений, заменяя его служебным маркером.

Обращение через квадратные скобки МоеСоответствие[Ключ] работает аналогично Получить() и тоже возвращает Неопределено при отсутствии ключа — исключения не возникает. Это удобно, но маскирует ошибки опечаток в ключах.

Поиск ключа по известному значению

Обратной операции — получить ключ по значению — в платформе нет. Задача решается перебором с условием:

НайденныйКлюч = Неопределено;

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

Если Элемент.Значение = ИскомоеЗначение Тогда

НайденныйКлюч = Элемент.Ключ;

Прервать;

КонецЕсли;

КонецЦикла;

Учтите, что значения в соответствии не уникальны: одному значению могут соответствовать несколько ключей. Команда «Прервать» вернёт первый попавшийся, а какой именно — не гарантируется из-за неопределённого порядка обхода. Если нужны все подходящие ключи, собирайте их в массив без прерывания цикла.

Для ссылочных значений сравнение через «=» работает корректно. Для сравнения сложных структур данных (массивов, таблиц) прямое сравнение не сработает — потребуется поэлементная проверка.

Особенности ключей разных типов

Строковые ключи чувствительны к регистру: «Контрагент» и «контрагент» — два разных ключа. Это отличие от структуры, где регистр значения не имеет. Перед вставкой и поиском строковых ключей приводите их к единому регистру через НРег() или ВРег(), если логика допускает нечувствительность.

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

Числовые ключи строго типизированы: число 1 и строка «1» — разные ключи. Смешение типов при формировании ключа — частая причина того, что Получить() возвращает Неопределено при визуально «правильном» ключе.

Типичные ошибки
01
Поиск строкового ключа в другом регистре — Получить() возвращает Неопределено, хотя ключ «на вид» есть
02
Смешение типов ключа: вставка по числу, поиск по строке — соответствие считает их разными ключами
03
Ожидание фиксированного порядка обхода — соответствие порядок не гарантирует
04
Повторная вставка существующего ключа без проверки — старое значение молча перезаписывается

Соответствие или структура: что выбрать

Если все ключи — строки-идентификаторы, часто удобнее структура: у неё есть метод Свойство(ИмяКлюча, НайденноеЗначение), который однозначно проверяет наличие ключа без проблемы с Неопределено. Структура также сохраняет порядок вставки при обходе.

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

Сравнение вариантов

Соответствие

Ключи любого типа, включая ссылки. Нет гарантии порядка, проверка ключа только через Получить() с неоднозначным Неопределено

Структура

Только строковые ключи-идентификаторы. Метод Свойство() точно проверяет наличие ключа, порядок обхода соответствует вставке

Список значений

Когда нужен порядок и сортировка, а поиск по ключу не критичен по скорости

Проверка результата и отладка

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

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

Контрольные точки

Как проверить результат

Тип ключа при поиске
Норма

Тип ключа в Получить() совпадает с типом при вставке

Тревожный признак

Вставка по строке, поиск по числу — результат Неопределено

Количество элементов
Норма

Совпадает с числом добавленных уникальных ключей

Тревожный признак

Меньше ожидаемого — ключи дублируются

Регистр строковых ключей
Норма

Единый регистр при вставке и поиске

Тревожный признак

Смешанный регистр — ключи не находятся

Частые вопросы

Есть ли у соответствия метод типа «ПолучитьКлючи»?

Нет, штатного метода получения списка ключей в платформе нет. Ключи собирают перебором «Для каждого КлючИЗначение Из Соответствие Цикл» с чтением свойства «Ключ» и добавлением в массив при необходимости.

Почему Получить() возвращает Неопределено, хотя ключ точно есть?

Чаще всего причина в несовпадении типа или регистра ключа: число вместо строки, другой регистр символов. Реже — ключ действительно отсутствует из-за того, что пара была удалена или соответствие пересоздано. Проверьте тип через ТипЗнч() и регистр строк.

Как отличить отсутствующий ключ от значения Неопределено?

Надёжный способ — перебор с прямым сравнением: «Если Элемент.Ключ = ИскомыйКлюч Тогда …». Альтернатива — не хранить Неопределено в значениях, используя служебный маркер, или перейти на структуру с методом Свойство().

Можно ли изменить ключ существующего элемента?

Напрямую нет. Нужно прочитать значение по старому ключу, удалить элемент методом Удалить(СтарыйКлюч), затем вставить пару с новым ключом через Вставить(НовыйКлюч, Значение).

Гарантирует ли соответствие порядок ключей при обходе?

Нет, порядок обхода соответствия не определён и может отличаться между итерациями и при передаче между клиентом и сервером. Если порядок важен, используйте структуру, список значений или сортируйте собранный массив ключей.

Что быстрее для поиска — соответствие или таблица значений?

Соответствие обеспечивает быстрый прямой доступ по ключу, тогда как поиск в таблице значений через Найти() работает по индексу или перебором. Для частого поиска по ключу соответствие предпочтительнее; таблица удобнее для многоколоночных данных и выгрузки в запросы.

Итог

Что важно запомнить

Ключи соответствия получают только перебором «Для каждого» через свойство «Ключ». Существование ключа проверяют через Получить(), помня о неоднозначности Неопределено. Следите за типом и регистром ключей и не рассчитывайте на порядок обхода.