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

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

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

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

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

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

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

Метод Найти — стандартный способ проверки

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

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

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

Массив.Добавить("Груша");

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

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

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

Иначе

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

КонецЕсли;

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

Если нужен не только факт наличия, но и позиция элемента, сохраните результат в переменную и используйте её для обращения к элементу: Элемент = Массив[Индекс]. Это избавляет от повторного поиска.

bsl
Индекс = Массив.Найти(ИскомоеЗначение);
Если Индекс <> Неопределено Тогда
    // значение есть, его позиция — Индекс
КонецЕсли;

Проверка вхождения перебором в цикле

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

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

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

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

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

Прервать;

КонецЕсли;

КонецЦикла;

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

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

Особенности сравнения ссылочных типов и разных типов данных

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

Сложнее обстоит дело с типами. Значение "001" (строка) и 1 (число) для массива — разные значения, автоматического приведения типов при поиске не происходит. Если массив заполнен из одного источника, а искомое значение пришло из другого (например, из параметра формы или JSON), сначала приведите типы к единому виду.

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

Типичные ошибки
01
Проверка «Если Массив.Найти(Х) Тогда» без сравнения с Неопределено — ошибка преобразования типа или неверная логика
02
Поиск строки в массиве чисел или наоборот — типы не приводятся автоматически, значение не находится
03
Поиск структуры методом Найти — структуры сравниваются по ссылке, совпадение по содержимому не обнаруживается
04
Отсутствие Прервать в цикле поиска — лишний обход всего массива после найденного элемента

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

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

Индекс = Новый Соответствие;

Для Каждого Значение Из Массив Цикл

Индекс.Вставить(Значение, Истина);

КонецЦикла;

// Быстрая проверка:

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

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

КонецЕсли;

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

Аналогичную роль может сыграть СписокЗначений с его методом НайтиПоЗначению(), но по скорости он сопоставим с линейным поиском по массиву, поэтому выигрыша для массовых проверок не даёт.

Сравнение вариантов

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

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

Перебор в цикле

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

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

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

СписокЗначений.НайтиПоЗначению()

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

Проверка нескольких значений и вложенных условий

На практике часто нужно проверить не одно значение, а набор: входит ли хотя бы один элемент списка А в массив Б, или все ли элементы присутствуют. Для первого случая достаточно цикла с флагом и Прервать; для второго — счётчика совпадений.

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

Для Каждого Значение Из Проверяемые Цикл

Если Массив.Найти(Значение) = Неопределено Тогда

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

Прервать;

КонецЕсли;

КонецЦикла;

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

Порядок действий
  1. 1
    Определите, сколько раз будет выполняться проверка: один раз или многократно в цикле
  2. 2
    Для разовой проверки используйте Массив.Найти(Значение) и сравните результат с Неопределено
  3. 3
    Для многократных проверок постройте Соответствие из значений массива и проверяйте через него
  4. 4
    Приведите типы искомого значения и элементов массива к единому виду
  5. 5
    Проверьте результат на тестовых данных: значение, которое есть, и значение, которого нет

Как убедиться, что проверка работает правильно

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

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

Ещё один источник скрытых ошибок — незначащие пробелы и разный регистр в строках. Строковое сравнение в 1С регистронезависимо, но пробелы учитываются: "Груша" и "Груша " — разные значения. При сомнениях применяйте СокрЛП() к обеим сторонам сравнения.

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

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

Значение, которое точно есть в массиве
Норма

Найти() вернул индекс (число от 0 и выше)

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

Вернулось Неопределено — проверяйте типы и пробелы

Значение, которого нет в массиве
Норма

Найти() вернул Неопределено

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

Вернулся индекс — возможно, сравнивается не то поле или значение

Поведение на пустом массиве
Норма

Найти() возвращает Неопределено, ошибок нет

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

Ошибка обращения к массиву — проверьте инициализацию переменной

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

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

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

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

Строковое сравнение во встроенном языке 1С регистронезависимо, поэтому Найти("груша") найдёт элемент "Груша". А вот пробелы и невидимые символы учитываются — при необходимости применяйте СокрЛП() к значениям перед сравнением.

Почему Найти() не находит структуру, которая точно есть в массиве?

Структуры сравниваются по ссылке на объект, а не по содержимому. Даже идентичная по полям структура — это другой объект. Перебирайте массив в цикле и сравнивайте конкретные поля каждого элемента.

Что быстрее: массив, список значений или соответствие?

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

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

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

Можно ли искать значение в фиксированном массиве?

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

Итог

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

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