Как правильно сопоставить элементы табличной части с массивом идентификаторов

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

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

Разберем по шагам несколько подходов, от простых до наиболее производительных, и выясним, какой из них лучше использовать в зависимости от объема данных.

Способ 1. Использование объекта Соответствие (оптимальный выбор)

Проанализируем работу с объектом Соответствие. Это один из самых быстрых способов поиска в памяти. В 1С Соответствие реализовано как хеш-таблица, что обеспечивает скорость поиска O(1), практически не зависящую от общего количества элементов.

Рассмотрим алгоритм реализации:

  1. Создаем объект Соответствие.
  2. Заполняем его элементами из массива, где ключом будет ID.
  3. В цикле обходим табличную часть и проверяем наличие ключа в соответствии.

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

// Обходим ТЧ и проверяем наличие ID
Для Каждого СтрокаТЧ Из Объект.ЗаказВПроизводство Цикл
    Если СлужебноеСоответствие[СтрокаТЧ.ID] <> Неопределено Тогда
        СтрокаТЧ.Значение = 1;
    КонецЕсли;
КонецЦикла;

Способ 2. Использование запроса и временных таблиц

Если данных очень много (десятки или сотни тысяч строк), эффективнее перенести обработку на сторону SQL-сервера. Выясним причину: база данных использует оптимизированные алгоритмы соединения (например, Hash Join или Merge Join).

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


Запрос = Новый Запрос;
Запрос.Текст = 
    "ВЫБРАТЬ
    |    ТаблицаИД.Ссылка КАК ID
    |ПОМЕСТИТЬ ВТ_ИскомыеИД
    |ИЗ
    |    &МассивИД КАК ТаблицаИД
    |;
    |////////////////////////////////////////////////////////////////////////////////
    |ВЫБРАТЬ
    |    ТЧ.НомерСтроки - 1 КАК Индекс
    |ИЗ
    |    Документ.ЗаказВПроизводство.Товары КАК ТЧ
    |        ВНУТРЕННЕЕ СОЕДИНЕНИЕ ВТ_ИскомыеИД КАК ВТ
    |        ПО ТЧ.ID = ВТ.ID
    |ГДЕ
    |    ТЧ.Ссылка = &Ссылка";

Запрос.УстановитьПараметр("МассивИД", МассивИД);
Запрос.УстановитьПараметр("Ссылка", Объект.Ссылка);

Результат = Запрос.Выполнить().Выгрузить();
Для Каждого СтрокаРез Из Результат Цикл
    Объект.ЗаказВПроизводство[СтрокаРез.Индекс].Значение = 1;
КонецЦикла;

Способ 3. Индексированная Таблица Значений

Если мы работаем не с объектом документа, а с выгруженной таблицей значений, мы можем задействовать метод НайтиСтроки(). Для этого крайне важно предварительно проиндексировать колонку ID.

Рассмотрим, как это ускоряет процесс:

  1. Выгружаем ТЧ в ТаблицаЗначений.
  2. Добавляем индекс: ТЗ.Индексы.Добавить("ID").
  3. Обходим массив идентификаторов и для каждого вызываем НайтиСтроки().

Важно: этот метод эффективен, когда массив идентификаторов значительно меньше, чем количество строк в таблице.

Способ 4. Алгоритм прямого индексирования (для числовых ID)

Проанализируем ситуацию, когда идентификаторы являются последовательными целыми числами. В этом случае можно использовать массив 1С как «карту присутствия», где индекс массива соответствует значению ID.


// Создаем массив размером с максимальный ID
МаксИД = 2000000; // Пример
КартаПрисутствия = Новый Массив(МаксИД + 1);

Для Каждого ТекID Из МассивИД Цикл
    КартаПрисутствия[ТекID] = Истина;
КонецЦикла;

Для Каждого СтрокаТЧ Из Объект.ЗаказВПроизводство Цикл
    // Прямое обращение по индексу - самая быстрая операция
    Если КартаПрисутствия[СтрокаТЧ.ID] = Истина Тогда
        СтрокаТЧ.Значение = 1;
    КонецЕсли;
КонецЦикла;

Этот метод является самым производительным в 1С (быстрее Соответствия), но имеет жесткие ограничения: ID должны быть только положительными целыми числами, а диапазон значений не должен превышать доступную оперативную память.

Резюме и рекомендации

Подведем итоги нашего исследования:

← На главную