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

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

1С: как узнать индекс элемента массива

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

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

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

Метод Найти(): базовый способ получить индекс

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

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

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

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

МассивТоваров.Добавить("Шурупы");

Индекс = МассивТоваров.Найти("Молоток");

// Индекс = 1

Сравнение выполняется по значению с учётом типа. Строка "10" и число 10 — разные значения, поиск одного по другому вернёт Неопределено. Для строк регистр букв также имеет значение: "Молоток" и "молоток" не совпадут.

bsl
Индекс = Массив.Найти(ИскомоеЗначение);
Если Индекс = Неопределено Тогда
    Сообщить("Элемент не найден");
Иначе
    Сообщить("Позиция: " + Индекс);
КонецЕсли;

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

Главная особенность — метод возвращает Неопределено, а не -1 и не 0, когда элемент отсутствует. Проверку нужно делать именно на Неопределено, иначе логика сломается: сравнение Индекс = -1 никогда не сработает, а обращение Массив[Неопределено] вызовет ошибку исполнения.

Типичный безопасный шаблон выглядит так:

Индекс = Массив.Найти(ИскомоеЗначение);

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

Элемент = Массив[Индекс];

// работа с найденным элементом

Иначе

// обработка ситуации "не найдено"

КонецЕсли;

Отдельная ловушка — индекс 0. Конструкция Если Индекс Тогда сработает как ложь для первого элемента массива, потому что 0 приводится к Ложь. Всегда сравнивайте с Неопределено явно.

Поиск индекса перебором циклом

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

ИндексНайденного = Неопределено;

Для Инд = 0 По Массив.ВГраница() Цикл

Если СтрНайти(Массив[Инд], "гвоздь") > 0 Тогда

ИндексНайденного = Инд;

Прервать;

КонецЕсли;

КонецЦикла;

Метод ВГраница() возвращает индекс последнего элемента — это удобнее и надёжнее, чем вычислять Количество() - 1. Оператор Прервать останавливает цикл после первого совпадения, экономя время на больших массивах.

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

Особые случаи: ссылки, структуры и регистр строк

Поиск ссылки в массиве

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

Поиск без учёта регистра

Для регистронезависимого сравнения приведите обе строки к одному регистру функцией НРег() или ВРег():

Для Инд = 0 По Массив.ВГраница() Цикл

Если НРег(Массив[Инд]) = НРег(ИскомоеЗначение) Тогда

ИндексНайденного = Инд;

Прервать;

КонецЕсли;

КонецЦикла;

Массивы структур

Метод Найти() для структур практически бесполезен: две структуры с одинаковым составом не считаются равными. Здесь всегда нужен цикл со сравнением конкретного ключа, например Массив[Инд].Код = ИскомыйКод.

Типичные ошибки
01
Проверка результата через «Если Индекс Тогда» — индекс 0 даёт Ложь, и первый элемент считается ненайденным
02
Сравнение с -1 вместо Неопределено — Найти() никогда не возвращает -1
03
Поиск строки без учёта регистра — «Молоток» и «молоток» не совпадают
04
Смешение типов: число 10 и строка «10» — разные значения, поиск не сработает
05
Использование Найти() для массива структур — одинаковые структуры не равны друг другу

Альтернативы: соответствие и список значений

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

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

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

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

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

Мгновенный поиск по ключу. Подходит, когда значения уникальны и поиск частый; индекса как такового нет

СписокЗначений

Есть метод НайтиПоЗначению(), возвращающий элемент, по которому доступен индекс через Индекс(). Удобен для связки значение+представление

ТаблицаЗначений

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

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

Маршрут решения

Как выбрать способ

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

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

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

Индекс = Массив.Найти(ИскомоеЗначение);

Сообщить("Индекс: " + ?(Индекс = Неопределено, "не найден", Индекс));

В отладчике удобно поставить точку останова сразу после строки поиска и посмотреть содержимое массива целиком — часто оказывается, что искомое значение отличается пробелом в конце или другим типом данных. Функция СокрЛП() перед сравнением убирает такие расхождения для строк.

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

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

Значение переменной Индекс после Найти()
Норма

Число от 0 до ВГраница() включительно

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

Неопределено при уверенности, что элемент есть

Фактический элемент по индексу
Норма

Массив[Индекс] равен искомому значению

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

Значение отличается — найден дубликат раньше нужного

Типы сравниваемых значений
Норма

ТипЗнч() совпадает у элемента и искомого

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

Строка сравнивается с числом или ссылкой

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

Что возвращает Найти(), если элемента нет в массиве?

Значение Неопределено. Не -1 и не 0 — поэтому проверку всегда делайте через сравнение с Неопределено, иначе условие сработает неверно.

Как найти индекс последнего вхождения значения?

Метод Найти() возвращает только первое совпадение. Для последнего переберите массив циклом без Прервать и сохраняйте индекс при каждом совпадении — в конце останется последняя позиция. Альтернатива — обратный цикл от ВГраница() до 0 с шагом -1 и остановкой на первом совпадении.

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

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

Можно ли найти индекс элемента в соответствии?

Нет, у соответствия нет индексов — доступ идёт по ключу. Если нужна позиция, используйте массив или список значений. Соответствие выбирают ради скорости поиска по ключу, а не ради порядка.

Как узнать индекс элемента в списке значений?

Сначала найдите элемент: Элемент = Список.НайтиПоЗначению(Значение). Если он не Неопределено, получите позицию: Индекс = Список.Индекс(Элемент). Нумерация также начинается с нуля.

Что быстрее — Найти() или перебор циклом?

Для простого равенства Найти() быстрее и короче, так как реализован на уровне платформы. Цикл оправдан только когда условие сложнее равенства. При частом поиске в большом массиве оба варианта проигрывают соответствию.

Итог

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

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