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