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