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

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

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

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

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

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

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

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

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

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

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

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

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

Индекс = Массив.Найти("Груша");

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

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

Иначе

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

КонецЕсли;

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

1c
Индекс = Массив.Найти(ИскомоеЗначение);
Если Индекс = Неопределено Тогда
    // элемент отсутствует
КонецЕсли;

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

Когда критерий поиска сложнее точного равенства — например, частичное совпадение строки или сравнение с приведением типов — используют цикл по индексам. Верхняя граница массива возвращается методом ВГраница(), он равен Количество() - 1.

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

Если СтрНайти(НРег(Массив[Индекс]), НРег("груша")) > 0 Тогда

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

Прервать;

КонецЕсли;

КонецЦикла;

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

Индекс = -1;

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

Индекс = Индекс + 1;

Если Элемент = ИскомоеЗначение Тогда

Прервать;

КонецЕсли;

КонецЦикла;

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

Поиск индекса структуры по значению поля

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

Решение — перебор с обращением к полю структуры:

// Массив структур вида: Новый Структура("Код, Наименование", ...)

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

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

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

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

Прервать;

КонецЕсли;

КонецЦикла;

Если под «строкой массива» имеется в виду таблица значений

В практике разработчиков под «строками массива» иногда подразумевают строки таблицы значений или табличной части. Это другие коллекции, и у них свои методы поиска. У таблицы значений применяют Найти() (по значению колонки), НайтиСтроки() (по структуре отбора) и Индекс() для определения позиции уже найденной строки.

Строка = ТаблицаЗначений.Найти(ИскомыйКод, "Код");

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

ИндексСтроки = ТаблицаЗначений.Индекс(Строка);

КонецЕсли;

У табличной части документа у строки есть свойство НомерСтроки — оно начинается с единицы, в отличие от индекса. Для получения индекса строки табличной части используют НомерСтроки - 1 или метод Индекс() табличной части.

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

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

Быстро для примитивных значений; не подходит для структур и частичного совпадения

Цикл по индексам

Универсально, любой критерий; медленнее при многократных поисках в большом массиве

Соответствие (ключ = значение)

Мгновенный поиск позиции при многократных обращениях; требует предварительного построения

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

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

Оптимизация: соответствие вместо повторного перебора

Если поиск индекса выполняется многократно внутри цикла, линейный перебор массива на каждой итерации заметно замедляет код. В этом случае массив заранее преобразуют в соответствие, где ключ — искомое значение, а значение — индекс:

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

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

Индексы.Вставить(Массив[Индекс], Индекс);

КонецЦикла;

// Дальше поиск — мгновенно:

Индекс = Индексы[ИскомоеЗначение]; // Неопределено, если нет

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

Типичные ошибки при работе с индексами

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

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

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

РеальныйИндекс = -Индекс;

Если Массив[РеальныйИндекс] = УдаляемоеЗначение Тогда

Массив.Удалить(РеальныйИндекс);

КонецЕсли;

КонецЦикла;

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

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

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

Значение результата Найти()
Норма

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

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

Неопределено при заведомо существующем значении — проверьте регистр и тип данных

Обращение Массив[Индекс]
Норма

Возвращается именно искомый элемент

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

Ошибка «Индекс за границами» — индекс не проверен или массив изменён

Поиск по полю структуры
Норма

Найден первый подходящий элемент, цикл прерван

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

Всегда Неопределено — использован Найти() со структурой вместо перебора

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

Итог

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

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

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

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

Метод возвращает значение Неопределено. Перед использованием результата как индекса его обязательно нужно проверить, иначе обращение Массив[Неопределено] вызовет ошибку исполнения.

Как найти индексы всех одинаковых элементов?

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

Почему Найти() не находит структуру, хотя поля совпадают?

Структуры сравниваются по ссылке на объект, а не по содержимому. Даже полностью идентичная по полям структура, созданная заново, не будет равна элементу массива. Ищите перебором с сравнением конкретного поля.

Чем отличается индекс от номера строки табличной части?

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

Как безопасно удалить элементы массива в цикле?

Перебирайте массив с конца — от ВГраница() к нулю. Тогда удаление текущего элемента не смещает позиции элементов, которые ещё предстоит проверить, и ничего не будет пропущено.

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

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