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

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

Как проверить, есть ли значение в массиве в 1С

Как проверить наличие значения в массиве 1С: метод Найти(), цикл перебора, соответствие и структура. Примеры кода, типичные ошибки и советы по производительности.

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

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

Проверка через метод Найти()

Метод Найти() — стандартный способ поиска элемента в массиве. Он принимает искомое значение и возвращает индекс первого совпадения (нумерация с нуля) либо Неопределено, если элемент не найден. Именно поэтому проверку нельзя строить через сравнение с нулём: индекс 0 — это валидная позиция первого элемента.

Типичный фрагмент кода выглядит так:

Массив = Новый Массив;

Массив.Добавить("Молоко");

Массив.Добавить("Хлеб");

Массив.Добавить("Сахар");

Если Массив.Найти("Хлеб") <> Неопределено Тогда

Сообщить("Значение найдено в массиве");

Иначе

Сообщить("Значение отсутствует");

КонецЕсли;

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

bsl
Индекс = Массив.Найти(ИскомоеЗначение);
Если Индекс <> Неопределено Тогда
    Сообщить("Найдено на позиции " + Индекс);
КонецЕсли;

Проверка перебором в цикле

Перебор через цикл Для Каждого применяется, когда простого сравнения недостаточно: например, нужно искать по части строки, по свойству объекта или с нестрогим условием. Метод Найти() сравнивает значения целиком, поэтому для сложных условий цикл — единственный вариант.

Найдено = Ложь;

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

Если СтрНайти(Элемент, "мол") > 0 Тогда

Найдено = Истина;

Прервать;

КонецЕсли;

КонецЦикла;

Команда Прервать важна: как только элемент найден, дальнейший перебор бессмысленен и только тратит время. Без прерывания на больших массивах цикл будет отрабатывать до конца даже после успешной находки.

Цикл также удобен, когда нужно подсчитать количество вхождений значения — Найти() такой возможности не даёт, он останавливается на первом совпадении.

Поиск ссылок, чисел и значений разных типов

Метод Найти() сравнивает значения с учётом типа. Строка "123" и число 123 — разные значения, и поиск не сработает, хотя визуально они похожи. Это одна из самых частых причин «непонятного» поведения: значение в массиве вроде бы есть, а проверка возвращает отсутствие.

Для ссылочных типов (справочники, документы) сравнение идёт по ссылке, а не по представлению. Две переменные, указывающие на один и тот же элемент справочника, считаются равными. Но если сравнивать ссылку с её строковым представлением или наименованием — совпадения не будет.

Особый случай — значение Неопределено. Массив может содержать такие элементы, и Массив.Найти(Неопределено) корректно находит их. Проверка результата через <> Неопределено при этом остаётся рабочей, путаницы не возникает.

Быстрая проверка через соответствие

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

Решение — один раз переложить массив в соответствие, где значения становятся ключами. Поиск ключа в соответствии работает значительно быстрее перебора:

Соответствие = Новый Соответствие;

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

Соответствие.Вставить(Элемент, Истина);

КонецЦикла;

// Дальше в любом месте кода:

Если Соответствие[ИскомоеЗначение] <> Неопределено Тогда

// значение есть

КонецЕсли;

Сравнение способов поиска

Массив.Найти()

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

Цикл Для Каждого

Нужен при нестрогих условиях поиска: часть строки, вычисляемое условие, подсчёт вхождений. Требует Прервать для экономии времени.

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

Оптимально при многократных проверках в больших массивах. Требует однократного заполнения и расходует дополнительную память.

Проверка в массиве структур и таблиц значений

Когда массив хранит не простые значения, а структуры или строки таблиц, метод Найти() бесполезен: структуры сравниваются по ссылке на объект, и два разных объекта с одинаковым содержимым не будут равны. Здесь нужен перебор со сравнением конкретных полей.

Для Каждого Строка Из МассивСтруктур Цикл

Если Строка.Артикул = ИскомыйАртикул Тогда

// найдена нужная строка

Прервать;

КонецЕсли;

КонецЦикла;

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

Типичные ошибки и как их избежать

Большинство проблем с проверкой наличия значения сводится к нескольким повторяющимся ошибкам. Их легко избежать, если знать о них заранее.

Типичные ошибки
01
Сравнение результата Найти() с нулём: индекс 0 — это первый элемент, поэтому проверять нужно только на Неопределено.
02
Поиск строки в массиве чисел или наоборот: типы должны совпадать, приведите значения к одному типу заранее.
03
Поиск ссылки по наименованию: сравнивайте ссылку со ссылкой, а не со строковым представлением.
04
Отсутствие Прервать в цикле после находки: лишний перебор сотен тысяч элементов замедляет обработку.
05
Использование Найти() внутри большого цикла: замените на соответствие, заполненное один раз.
06
Различие регистра в строках: 'Молоко' и 'молоко' — разные значения; при необходимости приводите обе строки через ВРег() или НРег().

Отдельно стоит упомянуть регистр строк. Метод Найти() сравнивает строки с учётом регистра, поэтому «Молоко» и «молоко» — разные значения. Если регистр не важен, приводите обе стороны сравнения к одному регистру через ВРег() или НРег() либо используйте цикл с СтрНайти().

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

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

Результат Найти()
Норма

Возвращён числовой индекс, элемент доступен по Массив[Индекс]

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

Возвращено Неопределено при заведомо присутствующем значении — проверьте типы и регистр

Тип искомого значения
Норма

ТипЗнч() совпадает с типом элементов массива

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

Типы различаются — сравнение всегда даёт отсутствие

Скорость обработки
Норма

Многократные проверки идут через соответствие

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

Найти() вызывается внутри большого цикла, обработка заметно тормозит

Выбор способа под задачу

Единственно верного способа нет — выбор зависит от размера данных, частоты проверок и природы условия поиска. Ориентируйтесь на простое правило: чем чаще выполняется проверка и чем больше массив, тем выгоднее подготовленные структуры данных вместо перебора.

Маршрут решения

Как выбрать способ

Разовая проверка в небольшом массиве простых значенийИспользуйте Массив.Найти(Значение) <> Неопределено
Нужен поиск по части строки или сложному условиюПеребирайте циклом Для Каждого с Прервать после находки
Проверка выполняется многократно в цикле по большим даннымПеренесите массив в соответствие и проверяйте по ключу
Данные уже в таблице значенийИспользуйте Найти() или НайтиСтроки() таблицы, массив не нужен
Массив содержит структуры или объектыПеребор со сравнением конкретных полей, Найти() не подходит

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

Что возвращает метод Найти(), если значения нет в массиве?

Метод возвращает значение Неопределено. Поэтому корректная проверка выглядит как Если Массив.Найти(Значение) <> Неопределено Тогда. Сравнивать результат с нулём нельзя: ноль — это индекс первого элемента массива.

Как проверить наличие строки без учёта регистра?

Метод Найти() сравнивает строки с учётом регистра. Чтобы игнорировать его, перебирайте массив циклом и сравнивайте ВРег(Элемент) = ВРег(Искомое), либо заранее приведите все элементы и искомое значение к одному регистру.

Можно ли найти в массиве ссылку на элемент справочника?

Да, метод Найти() корректно сравнивает ссылки: две переменные, указывающие на один объект базы, считаются равными. Главное — передавать именно ссылку, а не наименование или код в виде строки.

Что быстрее: Найти() по массиву или поиск в соответствии?

Для одной-двух проверок разница незаметна, и проще использовать Найти(). При многократных проверках в большом массиве соответствие заметно быстрее: поиск по ключу не требует перебора всех элементов. Заполнение соответствия делается один раз.

Как узнать, сколько раз значение встречается в массиве?

Метод Найти() находит только первое вхождение. Для подсчёта используйте цикл Для Каждого со счётчиком совпадений без команды Прервать — так вы пройдёте весь массив и посчитаете все вхождения.

Работает ли Найти() с массивом структур?

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

Итог

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

Для разовой проверки используйте Массив.Найти(Значение) <> Неопределено, следите за совпадением типов и регистра строк. При многократных проверках в больших массивах переносите данные в соответствие, а для сложных условий применяйте цикл с Прервать.