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

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

Как получить индекс элемента массива в 1С

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

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

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

Как устроена индексация массивов в 1С

Элементы массива нумеруются с нуля: первый элемент имеет индекс 0, последний — индекс, равный Количество() - 1. Для удобства есть метод ВГраница(), который возвращает индекс последнего элемента. Обращение по индексу выполняется через квадратные скобки: Массив[0].

Попытка обратиться к индексу за пределами диапазона вызовет ошибку исполнения «Индекс находится за границами массива». Поэтому перед обращением по вычисленному индексу всегда проверяйте, что он не меньше нуля и не больше ВГраница().

Метод Найти(): быстрый поиск первого вхождения

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

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

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

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

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

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

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

Сообщить("Найдено на позиции: " + Индекс); // выведет 1

Иначе

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

КонецЕсли;

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

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

Поиск индекса в цикле по условию

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

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

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

Если Массив[Индекс].Артикул = ИскомыйАртикул Тогда

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

Прервать;

КонецЕсли;

КонецЦикла;

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

Порядок действий при поиске в цикле
  1. 1
    Объявите переменную для результата и присвойте Неопределено
  2. 2
    Организуйте цикл Для Индекс = 0 По Массив.ВГраница()
  3. 3
    Внутри цикла проверьте условие для Массив[Индекс]
  4. 4
    При совпадении сохраните индекс и выполните Прервать
  5. 5
    После цикла проверьте результат на Неопределено перед использованием

Как проверить, что элемент найден, и избежать ошибок

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

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

Типичные ошибки
01
Использование результата Найти() без проверки на Неопределено — приводит к исключению при отсутствии элемента
02
Проверка Если Индекс > 0 — пропускает первый элемент массива с индексом 0
03
Сравнение значений разных типов: строка "10" не равна числу 10, поиск не сработает
04
Обращение к Массив[Индекс] без проверки границ — ошибка «Индекс за границами массива»

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

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

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

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

Метод Найти() массива

Подходит для разового поиска по точному равенству. Ограничение: только первое вхождение и строгое сравнение типов

Цикл с условием

Подходит для поиска по произвольному критерию и сбора всех вхождений. Ограничение: больше кода, линейное время

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

Подходит при многократных поисках по одному ключу. Ограничение: требует предварительного заполнения и памяти

Таблица значений с индексами

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

Практический пример: синхронизация двух списков

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

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

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

Индексы.Вставить(МассивЗаказа[Индекс].Артикул, Индекс);

КонецЦикла;

Для Каждого Артикул Из МассивИзФайла Цикл

Индекс = Индексы[Артикул];

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

// позиция найдена, можно обновить строку заказа

КонецЕсли;

КонецЦикла;

Обратите внимание: при дублях ключей в соответствии сохранится последний индекс. Если дубли возможны и важны, храните в значении массив индексов.

Контроль результата и отладка

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

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

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

Тип результата Найти()
Норма

Число от 0 до ВГраница() или осознанно обработанное Неопределено

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

Неопределено попадает в арифметику или в Удалить() без проверки

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

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

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

Ищется строка, а в массиве числа или ссылки

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

Строки совпадают с учётом регистра и без лишних пробелов

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

Невидимые различия: пробелы, неразрывные пробелы, разный регистр

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

Итог

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

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

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

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

Метод возвращает значение Неопределено. Перед использованием результата как индекса всегда проверяйте его сравнением с Неопределено, иначе при передаче в Удалить() или обращении по индексу возникнет ошибка исполнения.

Как найти индексы всех вхождений элемента, а не только первого?

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

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

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

Можно ли получить индекс элемента в цикле Для Каждого?

Напрямую нет — цикл Для Каждого перебирает сами значения без индексов. Либо используйте классический цикл Для с счётчиком от 0 до ВГраница(), либо заведите отдельную переменную-счётчик и увеличивайте её на каждой итерации.

Как удалить элемент по значению, если его индекс неизвестен?

Скомбинируйте два метода с проверкой: сначала Индекс = Массив.Найти(Значение), затем, если Индекс не равен Неопределено, выполните Массив.Удалить(Индекс). Без проверки код упадёт с ошибкой при отсутствии элемента.

Что быстрее для большого массива: Найти() или соответствие?

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