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