Разработка и Конфигурация · 9 мин
Как проверить, есть ли значение в массиве в 1С
Как проверить наличие значения в массиве 1С: метод Найти(), цикл перебора, соответствие и структура. Примеры кода, типичные ошибки и советы по производительности.
Проверка наличия значения в массиве — одна из самых частых задач при разработке на встроенном языке 1С. Она встречается при обработке списков документов, фильтрации номенклатуры, контроле дублей и построении отборов. Универсальный массив в 1С не имеет встроенного метода «Содержит», поэтому разработчику нужно знать несколько рабочих способов и понимать, когда какой из них применять.
Основной инструмент — метод Найти(), который возвращает индекс найденного элемента или Неопределено, если значения в массиве нет. Однако у него есть особенности: сравнение идёт по значению, типы данных должны совпадать, а для больших массивов линейный поиск может оказаться медленным. Ниже разобраны все практические варианты с готовыми примерами кода.
Проверка через метод Найти()
Метод Найти() — стандартный способ поиска элемента в массиве. Он принимает искомое значение и возвращает индекс первого совпадения (нумерация с нуля) либо Неопределено, если элемент не найден. Именно поэтому проверку нельзя строить через сравнение с нулём: индекс 0 — это валидная позиция первого элемента.
Типичный фрагмент кода выглядит так:
Массив = Новый Массив;
Массив.Добавить("Молоко");
Массив.Добавить("Хлеб");
Массив.Добавить("Сахар");
Если Массив.Найти("Хлеб") <> Неопределено Тогда
Сообщить("Значение найдено в массиве");
Иначе
Сообщить("Значение отсутствует");
КонецЕсли;
Если нужен не только факт наличия, но и позиция элемента, сохраните результат Найти() в переменную и используйте её для обращения к элементу или его удаления через Удалить(Индекс). Это избавляет от повторного поиска.
Индекс = Массив.Найти(ИскомоеЗначение);
Если Индекс <> Неопределено Тогда
Сообщить("Найдено на позиции " + Индекс);
КонецЕсли;Проверка перебором в цикле
Перебор через цикл Для Каждого применяется, когда простого сравнения недостаточно: например, нужно искать по части строки, по свойству объекта или с нестрогим условием. Метод Найти() сравнивает значения целиком, поэтому для сложных условий цикл — единственный вариант.
Найдено = Ложь;
Для Каждого Элемент Из Массив Цикл
Если СтрНайти(Элемент, "мол") > 0 Тогда
Найдено = Истина;
Прервать;
КонецЕсли;
КонецЦикла;
Команда Прервать важна: как только элемент найден, дальнейший перебор бессмысленен и только тратит время. Без прерывания на больших массивах цикл будет отрабатывать до конца даже после успешной находки.
Цикл также удобен, когда нужно подсчитать количество вхождений значения — Найти() такой возможности не даёт, он останавливается на первом совпадении.
Поиск ссылок, чисел и значений разных типов
Метод Найти() сравнивает значения с учётом типа. Строка "123" и число 123 — разные значения, и поиск не сработает, хотя визуально они похожи. Это одна из самых частых причин «непонятного» поведения: значение в массиве вроде бы есть, а проверка возвращает отсутствие.
Для ссылочных типов (справочники, документы) сравнение идёт по ссылке, а не по представлению. Две переменные, указывающие на один и тот же элемент справочника, считаются равными. Но если сравнивать ссылку с её строковым представлением или наименованием — совпадения не будет.
Особый случай — значение Неопределено. Массив может содержать такие элементы, и Массив.Найти(Неопределено) корректно находит их. Проверка результата через <> Неопределено при этом остаётся рабочей, путаницы не возникает.
Быстрая проверка через соответствие
Если проверку наличия нужно выполнять многократно — например, внутри цикла по тысячам строк табличной части — линейный поиск по массиву станет узким местом. Каждый вызов Найти() в худшем случае просматривает весь массив, и суммарное время растёт квадратично.
Решение — один раз переложить массив в соответствие, где значения становятся ключами. Поиск ключа в соответствии работает значительно быстрее перебора:
Соответствие = Новый Соответствие;
Для Каждого Элемент Из Массив Цикл
Соответствие.Вставить(Элемент, Истина);
КонецЦикла;
// Дальше в любом месте кода:
Если Соответствие[ИскомоеЗначение] <> Неопределено Тогда
// значение есть
КонецЕсли;
Сравнение способов поиска
Подходит для разовых проверок и небольших массивов. Простой код, но линейный перебор при каждом вызове.
Нужен при нестрогих условиях поиска: часть строки, вычисляемое условие, подсчёт вхождений. Требует Прервать для экономии времени.
Оптимально при многократных проверках в больших массивах. Требует однократного заполнения и расходует дополнительную память.
Проверка в массиве структур и таблиц значений
Когда массив хранит не простые значения, а структуры или строки таблиц, метод Найти() бесполезен: структуры сравниваются по ссылке на объект, и два разных объекта с одинаковым содержимым не будут равны. Здесь нужен перебор со сравнением конкретных полей.
Для Каждого Строка Из МассивСтруктур Цикл
Если Строка.Артикул = ИскомыйАртикул Тогда
// найдена нужная строка
Прервать;
КонецЕсли;
КонецЦикла;
Если данные уже находятся в таблице значений, массив вообще не нужен: используйте метод Найти() таблицы значений, который ищет по значению в указанной колонке, или НайтиСтроки() с отбором по нескольким полям. Это штатные и быстрые механизмы платформы.
Типичные ошибки и как их избежать
Большинство проблем с проверкой наличия значения сводится к нескольким повторяющимся ошибкам. Их легко избежать, если знать о них заранее.
Отдельно стоит упомянуть регистр строк. Метод Найти() сравнивает строки с учётом регистра, поэтому «Молоко» и «молоко» — разные значения. Если регистр не важен, приводите обе стороны сравнения к одному регистру через ВРег() или НРег() либо используйте цикл с СтрНайти().
Как проверить результат
Возвращён числовой индекс, элемент доступен по Массив[Индекс]
Возвращено Неопределено при заведомо присутствующем значении — проверьте типы и регистр
ТипЗнч() совпадает с типом элементов массива
Типы различаются — сравнение всегда даёт отсутствие
Многократные проверки идут через соответствие
Найти() вызывается внутри большого цикла, обработка заметно тормозит
Выбор способа под задачу
Единственно верного способа нет — выбор зависит от размера данных, частоты проверок и природы условия поиска. Ориентируйтесь на простое правило: чем чаще выполняется проверка и чем больше массив, тем выгоднее подготовленные структуры данных вместо перебора.
Как выбрать способ
Частые вопросы
Что возвращает метод Найти(), если значения нет в массиве?
Метод возвращает значение Неопределено. Поэтому корректная проверка выглядит как Если Массив.Найти(Значение) <> Неопределено Тогда. Сравнивать результат с нулём нельзя: ноль — это индекс первого элемента массива.
Как проверить наличие строки без учёта регистра?
Метод Найти() сравнивает строки с учётом регистра. Чтобы игнорировать его, перебирайте массив циклом и сравнивайте ВРег(Элемент) = ВРег(Искомое), либо заранее приведите все элементы и искомое значение к одному регистру.
Можно ли найти в массиве ссылку на элемент справочника?
Да, метод Найти() корректно сравнивает ссылки: две переменные, указывающие на один объект базы, считаются равными. Главное — передавать именно ссылку, а не наименование или код в виде строки.
Что быстрее: Найти() по массиву или поиск в соответствии?
Для одной-двух проверок разница незаметна, и проще использовать Найти(). При многократных проверках в большом массиве соответствие заметно быстрее: поиск по ключу не требует перебора всех элементов. Заполнение соответствия делается один раз.
Как узнать, сколько раз значение встречается в массиве?
Метод Найти() находит только первое вхождение. Для подсчёта используйте цикл Для Каждого со счётчиком совпадений без команды Прервать — так вы пройдёте весь массив и посчитаете все вхождения.
Работает ли Найти() с массивом структур?
Формально работает, но бесполезно: структуры сравниваются по ссылке на объект, а не по содержимому. Две структуры с одинаковыми полями не равны. Ищите перебором, сравнивая значения конкретных ключей структуры.
Что важно запомнить
Для разовой проверки используйте Массив.Найти(Значение) <> Неопределено, следите за совпадением типов и регистра строк. При многократных проверках в больших массивах переносите данные в соответствие, а для сложных условий применяйте цикл с Прервать.