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