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

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

Как найти строку в массиве в 1С: все способы с примерами

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

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

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

Метод Найти(): поиск точного совпадения

У объекта «Массив» есть встроенный метод Найти(Значение). Он выполняет последовательное сравнение каждого элемента с искомым значением и возвращает индекс первого найденного элемента. Индексация массивов в 1С начинается с нуля, поэтому первый элемент имеет индекс 0. Если совпадений нет, метод возвращает значение Неопределено.

МассивГородов = Новый Массив;

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

МассивГородов.Добавить("Казань");

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

Индекс = МассивГородов.Найти("Казань");

Если Индекс = Неопределено Тогда

Сообщить("Элемент не найден");

Иначе

Сообщить("Найден элемент с индексом: " + Индекс); // 1

КонецЕсли;

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

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

Поиск перебором в цикле: когда Найти() недостаточно

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

ИскомаяПодстрока = "казан";

НайденныйЭлемент = Неопределено;

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

Если СтрНайти(НРег(Элемент), НРег(ИскомаяПодстрока)) > 0 Тогда

НайденныйЭлемент = Элемент;

Прервать;

КонецЕсли;

КонецЦикла;

Если НайденныйЭлемент <> Неопределено Тогда

Сообщить("Найдено: " + НайденныйЭлемент);

КонецЕсли;

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

Если нужны все совпадения, а не первое, вместо Прервать собирайте результаты в новый массив:

Результат = Новый Массив;

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

Если СтрНайти(НРег(Элемент), НРег(ИскомаяПодстрока)) > 0 Тогда

Результат.Добавить(Элемент);

КонецЕсли;

КонецЦикла;

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

Проверка вхождения без получения индекса

Часто индекс не нужен — требуется только ответить на вопрос «есть ли такое значение в массиве». Типовой сценарий: проверить, входит ли значение в список допустимых, например разрешён ли у пользователя доступ к складу из списка. Здесь тот же метод Найти() используется как условие:

ДопустимыеСклады = ПолучитьДопустимыеСклады(); // массив ссылок

Если ДопустимыеСклады.Найти(ТекущийСклад) = Неопределено Тогда

ВызватьИсключение "Склад недоступен текущему пользователю";

КонецЕсли;

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

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

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

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

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

// работа с найденной строкой

Прервать;

КонецЕсли;

КонецЦикла;

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

Отбор = Новый Структура;

Отбор.Вставить("Артикул", ИскомыйАртикул);

Отбор.Вставить("Склад", ТекущийСклад);

НайденныеСтроки = ТаблицаТоваров.НайтиСтроки(Отбор);

Для Каждого Строка Из НайденныеСтроки Цикл

// обработка каждой найденной строки

КонецЦикла;

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

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

Точное совпадение простых значений и ссылок. Быстро и коротко, но без поиска по части строки и без учёта регистра.

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

Гибкие условия: подстрока, регистр, вычисляемые проверки. Требует больше кода, при больших объёмах — внимание к Прервать.

Таблица значений + НайтиСтроки()

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

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

Когда поиск выполняется многократно по ключу: ключ — строка, значение — произвольные данные. Выборка по ключу без перебора.

Оптимизация: соответствие вместо массива при частом поиске

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

Решение — использовать объект «Соответствие», где искомая строка является ключом. Выборка из соответствия по ключу не требует перебора и выполняется практически мгновенно независимо от размера:

// Однократно строим соответствие из массива

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

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

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

КонецЦикла;

// Далее многократно проверяем вхождение без перебора

Если СоответствиеПоиска.Получить(ИскомоеЗначение) <> Неопределено Тогда

// значение присутствует

КонецЕсли;

Тот же приём работает наоборот: если нужно получить по строке связанные данные (например, по артикулу — ссылку на номенклатуру), соответствие избавляет от повторных запросов к базе внутри цикла. Это одна из базовых техник ускорения обработок загрузки данных.

Частая причина «поиск не находит то, что точно есть» — непечатаемые символы: неразрывный пробел, перенос строки, символ табуляции в данных, пришедших из Excel или внешних файлов. Перед поиском очищайте строки функцией СокрЛП(), а при разборе файлов дополнительно заменяйте символы неразрывного пробела на обычные.
ПЗ
Практическое замечание

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

Первая группа ошибок связана с неверной интерпретацией результата. Метод Найти() возвращает Неопределено при отсутствии элемента, и попытка использовать это значение как число (например, обратиться к Массив[Индекс] без проверки) приведёт к ошибке исполнения. Всегда проверяйте результат перед использованием.

Вторая группа — несовпадение типов и регистра. Строка из пользовательского ввода может содержать лишние пробелы по краям, другой регистр, а числовые значения могут храниться в массиве как числа, а искаться как строки. Унифицируйте данные перед сравнением: СокрЛП(), НРег(), приведение типов через Строка() или Число().

Типичные ошибки
01
Использование результата Найти() без проверки на Неопределено — обращение к Массив[Неопределено] вызывает ошибку исполнения
02
Поиск строки без учёта регистра: «казань» не находится среди «Казань» — приводите обе строки к одному регистру
03
Сравнение разных типов: число 5 и строка «5» не равны — приводите типы перед поиском
04
Поиск ссылки по её строковому представлению — сначала получите ссылку, затем ищите её в массиве
05
Лишние пробелы и непечатаемые символы в данных из файлов — используйте СокрЛП() перед сравнением
06
Перебор большого массива внутри другого цикла вместо соответствия — резкое падение производительности

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

Проверка результата и отладка

При отладке поиска полезно вывести содержимое массива и искомое значение рядом. В конфигураторе это делается через точку останова и табло: добавьте в табло выражение МассивГородов (его можно развернуть и посмотреть все элементы с типами) и выражение МассивГородов.Найти(ИскомоеЗначение). Так сразу видно, совпадают ли типы и есть ли значение в массиве в принципе.

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

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

Возвращаемое значение Найти()
Норма

Число от 0 до (Количество-1) — индекс найденного элемента

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

Неопределено — элемент не найден, обращаться к Массив[Индекс] нельзя

Типы данных в табло отладчика
Норма

Тип искомого значения совпадает с типом элементов массива

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

Ищется строка, а в массиве числа или ссылки — сравнение всегда ложно

Содержимое строк
Норма

Строки совпадают посимвольно, без лишних пробелов

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

Ведущие/конечные пробелы, разный регистр, непечатаемые символы

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

Итог

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

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

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

Как найти строку в массиве без учёта регистра?

Метод Найти() этого не умеет — используйте перебор в цикле со сравнением НРег(Элемент) = НРег(ИскомаяСтрока). Либо заранее приведите все элементы массива и искомую строку к одному регистру и тогда применяйте Найти().

Что вернёт Найти(), если в массиве несколько одинаковых строк?

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

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

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

Как проверить, что массив вообще заполнен, перед поиском?

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

Чем поиск в массиве отличается от поиска в списке значений?

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

Как найти строку в массиве на клиенте в управляемых формах?

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