Как проверить, принадлежит ли элемент массиву в 1С?

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

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

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

Способ 1. Базовый поиск в массиве с помощью метода Найти()

Для стандартных массивов, содержащих простые типы данных (числа, строки, даты) или ссылки на объекты базы данных (справочники, документы, планы счетов), в платформе 1С предусмотрен встроенный метод Найти().

Синтаксис метода выглядит следующим образом:

Индекс = Массив.Найти(ИскомоеЗначение);

Метод возвращает Индекс найденного элемента (нумерация начинается с 0), если элемент присутствует в массиве. Если элемент не найден, метод возвращает значение Неопределено.

Рассмотрим практический пример проверки вхождения счета в массив:


// Создаем и заполняем массив счетами учета
СчетаМассив = Новый Массив;
СчетаМассив.Добавить(ПланыСчетов.Хозрасчетный.ТоварыНаСкладах); // 41.01
СчетаМассив.Добавить(ПланыСчетов.Хозрасчетный.Материалы);       // 10.01

// Определяем счет, который нужно проверить
ИскомыйСчет = ПланыСчетов.Хозрасчетный.Материалы;

// Проверяем вхождение
Если СчетаМассив.Найти(ИскомыйСчет) <> Неопределено Тогда
    Сообщить("Счет найден в массиве, доступ разрешен.");
Иначе
    Сообщить("Счет не найден в массиве!");
КонецЕсли;

Важные особенности работы метода Найти():

  1. Строгое соответствие типов: Метод выполняет поиск с учетом типов данных. Например, если в вашем массиве хранятся строки "10.01", а вы попытаетесь найти число 10.01, метод вернет Неопределено.
  2. Сравнение ссылочных типов: При поиске ссылок платформа сравнивает их уникальные идентификаторы (GUID), а не текстовые представления.
  3. Чувствительность к регистру: При поиске строковых значений сравнение по умолчанию выполняется без учета регистра символов, однако наличие пробелов в начале или конце строки может повлиять на результат.

Типичная ошибка: Поиск значения в массиве строк таблицы значений

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

Представим ситуацию: у нас есть ТаблицаЗначений с колонкой "КодТовара". Мы пытаемся найти строки по определенному условию с помощью метода НайтиСтроки(), а затем хотим проверить, есть ли в полученном результате конкретный код:


// Выполняем поиск строк по отбору
ПараметрыОтбора = Новый Структура("Статус", "Активен");
НайденныеСтроки = ТаблицаЗначений.НайтиСтроки(ПараметрыОтбора);

// Пытаемся найти конкретный код товара в полученном результате
// ВНИМАНИЕ: Этот код работать НЕ БУДЕТ!
Индекс = НайденныеСтроки.Найти(2550); 

Выясним причину, почему этот код не работает:

Метод НайтиСтроки() возвращает объект типа Массив. Однако элементами этого массива являются не числа и не строки из колонок таблицы, а объекты типа СтрокаТаблицыЗначений. Каждый элемент такого массива — это сложная структура данных (вся строка целиком).

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

Как правильно искать значения в таблицах значений

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

Вариант А. Выгрузка конкретной колонки в "плоский" массив

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


// Выгружаем все значения колонки "КодТовара" в простой массив
МассивКодов = ТаблицаЗначений.ВыгрузитьКолонку("КодТовара");

// Теперь в массиве лежат чистые числа/строки, поиск отработает корректно
Индекс = МассивКодов.Найти(2550);
Если Индекс <> Неопределено Тогда
    Сообщить("Код найден! Номер строки в исходной таблице: " + Индекс);
КонецЕсли;

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

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


// Ищем непосредственно в таблице значений, указав имя колонки
НайденнаяСтрока = ТаблицаЗначений.Найти(2550, "КодТовара");

Если НайденнаяСтрока <> Неопределено Тогда
    Сообщить("Значение успешно найдено в таблице!");
    // Мы можем сразу обратиться к данным найденной строки:
    Сообщить("Наименование товара: " + НайденнаяСтрока.Наименование);
КонецЕсли;

Оптимизация поиска: Использование "Соответствия" для больших массивов

Обратите внимание на производительность алгоритмов. Метод Массив.Найти() осуществляет последовательный линейный обход всех элементов (сложность $O(N)$). Если ваш массив содержит десятки тысяч элементов, а проверка выполняется в цикле многократно, это приведет к серьезному замедлению работы программы.

Для быстрой проверки вхождения элемента в список рекомендуется использовать объект Соответствие (аналог Map/Хэш-таблицы). Поиск ключа в объекте Соответствие работает практически мгновенно (сложность близка к $O(1)$), независимо от размера коллекции.

Проанализируем пример оптимизации:


// Вместо массива используем Соответствие
БыстрыйРеестр = Новый Соответствие;
БыстрыйРеестр.Вставить("10.01", Истина);
БыстрыйРеестр.Вставить("10.02", Истина);
БыстрыйРеестр.Вставить("10.03", Истина);

// Проверяемый элемент
ИскомыйСчет = "10.01";

// Моментальная проверка вхождения без перебора всей коллекции
Если БыстрыйРеестр[ИскомыйСчет] <> Неопределено Тогда
    Сообщить("Элемент входит в реестр!");
КонецЕсли;

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


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