Какой объект 1С выбрать для хранения уникальных ключей с возможностью обращения по индексу?

Программист 1С v8.3 (Управляемые формы) IT и автоматизация бизнеса
← На главную

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

Анализ ограничений стандартных объектов 1С

Проанализируем основные универсальные коллекции 1С и их особенности при работе с уникальными данными:

  1. Соответствие: Обладает удобным методом Вставить(), который автоматически перезаписывает значение при совпадении ключа и предотвращает появление дублей. Однако Соответствие основано на хеш-таблице, не хранит порядок добавления элементов и не позволяет обращаться к элементам по индексу (вызов МоеСоответствие[0] вызовет ошибку).
  2. Структура: Также позволяет быстро обращаться по ключу, но ключами могут выступать только строки-идентификаторы. Обращение по числовому индексу не поддерживается.
  3. СписокЗначений: Идеально подходит для хранения пар «Значение» и «Представление», поддерживает индексацию (СписокЗначений[0]), доступен как на сервере, так и на клиенте. Но методы Добавить() и Вставить() не проверяют уникальность добавляемых данных.
  4. ТаблицаЗначений: Поддерживает структуру из любых колонок, индексацию для быстрого поиска и доступ по индексу строки. Стоит учитывать, что ТаблицаЗначений недоступна в контексте тонкого и веб-клиента.

Вариант 1. Использование Таблицы Значений с индексами

Рассмотрим вариант создания собственной структуры на базе объекта ТаблицаЗначений. Чтобы поиск работал максимально быстро, добавим индекс по ключевой колонке.

Посмотрим на пример кода:


// Создаем таблицу значений и добавляем колонки
ТЗДанные = Новый ТаблицаЗначений;
ТЗДанные.Колонки.Добавить("Ключ");
ТЗДанные.Колонки.Добавить("Значение");

// Добавляем индекс для ускорения поиска
ТЗДанные.Индексы.Добавить("Ключ");

// Пример добавления элемента с проверкой уникальности
НайденнаяСтрока = ТЗДанные.Найти(НовыйКлюч, "Ключ");
Если НайденнаяСтрока = Неопределено Тогда
    НайденнаяСтрока = ТЗДанные.Добавить();
    НайденнаяСтрока.Ключ = НовыйКлюч;
КонецЕсли;
НайденнаяСтрока.Значение = НовоеЗначение;

// Обращение к первому элементу по индексу
Если ТЗДанные.Количество() > 0 Тогда
    ПервыйКлюч = ТЗДанные[0].Ключ;
    ПервоеЗначение = ТЗДанные[0].Значение;
КонецЕсли;

Данный подход гарантирует уникальность ключей, сохраняет порядок добавления строк и позволяет обращаться к элементам по индексу ТЗДанные[0].

Вариант 2. Использование Списка Значений с предварительной проверкой

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

Разберем по шагам реализацию этого способа:


МойСписок = Новый СписокЗначений;

// Проверяем наличие элемента перед добавлением
НайденныйЭлемент = МойСписок.НайтиПоЗначению(НовоеЗначение);
Если НайденныйЭлемент = Неопределено Тогда
    МойСписок.Добавить(НовоеЗначение, НовоеПредставление);
КонецЕсли;

// Получение первого элемента по индексу
Если МойСписок.Количество() > 0 Тогда
    ПервыйЭлемент = МойСписок[0];
    ЗначениеПервого = ПервыйЭлемент.Значение;
    ПредставлениеПервого = ПервыйЭлемент.Представление;
КонецЕсли;

Этот метод легок в написании, прекрасно подходит для небольших коллекций и работает во всех контекстах выполнения кода.

Вариант 3. Паттерн «Массив + Соответствие»

Когда требуется обработка большого массива данных и важна высокая скорость работы O(1), объединим два объекта: Массив для сохранения порядка и индексации и Соответствие для моментальной проверки уникальности.


КоллекцияМассив = Новый Массив;
ИндексСоответствие = Новый Соответствие;

// Добавление элемента
Если ИндексСоответствие.Получить(НовыйКлюч) = Неопределено Тогда
    ИндексСоответствие.Вставить(НовыйКлюч, Истина);
    КоллекцияМассив.Добавить(НовыйКлюч);
КонецЕсли;

// Быстрый доступ к первому элементу по индексу
Если КоллекцияМассив.Количество() > 0 Тогда
    ПервыйКлюч = КоллекцияМассив[0];
КонецЕсли;

Вариант 4. Прерывание обхода Соответствия

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


НужныйКлюч = Неопределено;
Для Каждого КлючИЗначение Из МоеСоответствие Цикл
    НужныйКлюч = КлючИЗначение.Ключ;
    Прервать;
КонецЦикла;

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

← На главную