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

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

Как найти максимум в массиве 1С: рабочие способы с примерами

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

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

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

Все примеры написаны на встроенном языке 1С и работают как в управляемых, так и в обычных формах, на толстом и тонком клиенте, если не указано иное.

Классический способ: поиск максимума перебором в цикле

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

Функция НайтиМаксимум(МассивЧисел)

Если МассивЧисел.Количество() = 0 Тогда

Возврат Неопределено;

КонецЕсли;

МаксЗначение = МассивЧисел[0];

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

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

МаксЗначение = Элемент;

КонецЕсли;

КонецЦикла;

Возврат МаксЗначение;

КонецФункции

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

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

bsl
МаксЗначение = МассивЧисел[0];
Для Каждого Элемент Из МассивЧисел Цикл
    Если Элемент > МаксЗначение Тогда
        МаксЗначение = Элемент;
    КонецЕсли;
КонецЦикла;

Как найти максимум вместе с индексом элемента

Часто недостаточно знать само максимальное значение — нужно ещё понять, где оно находится в массиве. Например, чтобы потом удалить этот элемент, заменить его или получить связанные данные из параллельного массива.

Функция НайтиИндексМаксимума(МассивЧисел)

Если МассивЧисел.Количество() = 0 Тогда

Возврат -1;

КонецЕсли;

ИндексМакс = 0;

МаксЗначение = МассивЧисел[0];

Для Индекс = 1 По МассивЧисел.Количество() - 1 Цикл

Если МассивЧисел[Индекс] > МаксЗначение Тогда

МаксЗначение = МассивЧисел[Индекс];

ИндексМакс = Индекс;

КонецЕсли;

КонецЦикла;

Возврат ИндексМакс;

КонецФункции

Здесь используется цикл со счётчиком, а не «Для Каждого», потому что нужен индекс. Если максимальных значений несколько, переменная ИндексМакс укажет на первое из них — сравнение строгое («больше», а не «больше или равно»), поэтому при равенстве замена не происходит. Если нужен последний из максимальных элементов, замените условие на «>=».

Максимум по нескольким критериям

Если элементы массива — структуры, максимум обычно ищут по одному из полей. Логика та же, только сравнивается конкретное свойство, а запоминается вся структура или её индекс. Это типичная ситуация при обработке строк заказов, остатков или результатов расчётов.

Поиск максимума через сортировку массива

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

Список = Новый СписокЗначений;

Список.ЗагрузитьЗначения(МассивЧисел);

Список.СортироватьПоЗначению(НаправлениеСортировки.Убыв);

МаксЗначение = Список[0].Значение;

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

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

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

Перебор в цикле

Универсальный и быстрый вариант: один проход, сохраняется индекс, работает с любыми сравнимыми типами. Требует аккуратной обработки пустого массива.

Сортировка через СписокЗначений

Короткий код, удобно, когда нужны несколько наибольших значений или сам массив нужен отсортированным. Медленнее цикла и теряет связь с исходными индексами.

Свёртка таблицы значений

Подходит, когда данные уже в таблице и нужен максимум по группам. Избыточна для простого одномерного массива чисел.

Максимум по колонке таблицы значений через свёртку

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

ТаблицаДанных.Сортировать("Сумма Убыв");

Если ТаблицаДанных.Количество() > 0 Тогда

МаксСумма = ТаблицаДанных[0].Сумма;

КонецЕсли;

Альтернатива — найти максимум прямо в запросе функцией МАКСИМУМ(). Если данные приходят из информационной базы, это самый эффективный путь: СУБД выполнит агрегацию на своей стороне, и в код 1С попадёт уже готовое значение.

Запрос = Новый Запрос;

Запрос.Текст =

"ВЫБРАТЬ

| МАКСИМУМ(Продажи.СуммаОборот) КАК МаксСумма

|ИЗ

| РегистрНакопления.Продажи.Обороты КАК Продажи";

Выборка = Запрос.Выполнить().Выбрать();

Если Выборка.Следующий() Тогда

МаксСумма = Выборка.МаксСумма;

КонецЕсли;

Правило простое: данные в массиве — ищем циклом, данные в таблице — сортировкой или циклом по строкам, данные в базе — агрегатной функцией запроса. Перекладывать данные из базы в массив только ради поиска максимума не нужно.

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

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

Данные в одномерном массиве чисел, нужен только максимумИспользуйте перебор в цикле с проверкой на пустой массив
Нужен максимум и его позиция в массивеПрименяйте цикл со счётчиком и переменной для индекса
Нужно несколько наибольших значенийОтсортируйте СписокЗначений по убыванию и возьмите первые элементы
Данные находятся в информационной базеПолучите максимум функцией МАКСИМУМ() прямо в запросе

Особенности для разных типов данных

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

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

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

Если ТипЗнч(Элемент) <> Тип("Число") Тогда

Продолжить;

КонецЕсли;

Если МаксЗначение = Неопределено Или Элемент > МаксЗначение Тогда

МаксЗначение = Элемент;

КонецЕсли;

КонецЦикла;

Обратите внимание на инициализацию: если первый элемент может быть неподходящим, начинайте с МаксЗначение = Неопределено и проверяйте это в условии. Иначе нечисловой первый элемент «застрянет» в переменной максимума.

Проверка результата и типичные ошибки

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

Особенно коварен случай с отрицательными числами. Если инициализировать максимум нулём вместо первого элемента, то для массива из одних отрицательных чисел функция вернёт 0, которого в массиве вообще нет. Инициализация первым элементом массива полностью снимает эту проблему.

Типичные ошибки
01
Инициализация максимума нулём вместо первого элемента — на массиве из отрицательных чисел функция вернёт несуществующее значение 0.
02
Поиск максимума без проверки пустого массива — обращение к Массив[0] приводит к ошибке индекса за границами.
03
Использование в цикле верхней границы Количество() вместо Количество() - 1 — выход за пределы массива из-за нумерации с нуля.
04
Игнорирование значений NULL и смешанных типов — непредсказуемый результат сравнения или падение кода.
05
Сортировка исходного массива ради одного максимума — лишние вычисления и потеря исходного порядка элементов.
Контрольные точки

Как проверить корректность функции

Массив из одного элемента
Норма

Функция возвращает этот элемент

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

Ошибка или возврат Неопределено

Все элементы отрицательные
Норма

Возвращается наибольшее отрицательное число

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

Возвращается 0, которого нет в массиве

Пустой массив
Норма

Возвращается Неопределено или -1 без ошибки

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

Ошибка «Индекс за границами массива»

Несколько одинаковых максимумов
Норма

Возвращается корректное значение, индекс — первого вхождения

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

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

Ответы на частые вопросы

Есть ли в 1С встроенная функция Макс() для массива?

Нет, встроенной функции поиска максимума для массивов в языке 1С не существует. Функция Макс() встречается только в языке выражений системы компоновки данных и в некоторых других контекстах. Для массива максимум ищут циклом, сортировкой или через запрос с агрегатной функцией МАКСИМУМ().

Как найти минимум в массиве?

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

Как найти максимум в массиве структур по одному из полей?

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

Что вернуть из функции, если массив пустой?

Общепринятый вариант — вернуть Неопределено, а вызывающий код проверяет результат перед использованием. Для функции, возвращающей индекс, удобно возвращать -1: такое значение невозможно получить при нормальной работе, и его легко отличить. Выбрасывать исключение стоит только если пустой массив — действительно аварийная ситуация в вашей логике.

Что быстрее: цикл или сортировка?

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

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

Используйте запрос с агрегатной функцией МАКСИМУМ() по нужному полю. Это самый эффективный способ: вычисление выполняется на стороне СУБД, а в код возвращается одно готовое значение. Выгружать тысячи записей в таблицу или массив ради поиска одного максимума не следует.

Итог

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

Для поиска максимума в массиве 1С используйте перебор в цикле с инициализацией первым элементом и обязательной проверкой на пустой массив. Сортировка оправдана, когда нужно несколько наибольших значений, а для данных из базы применяйте функцию МАКСИМУМ() в запросе. Всегда учитывайте нумерацию массивов с нуля, отрицательные числа и возможные значения NULL.