Сортировка массива в 1С: у Массива нет метода, но есть три рабочих обхода

· 9 мин

Содержание

Многие ищут у объекта Массив метод вроде Сортировать() или СортироватьПоВозрастанию(). Его нет. Ни в 8.3, ни в более ранних версиях платформы у массива нет встроенной сортировки, и код с таким вызовом упадёт с ошибкой «Метод объекта не обнаружен ».

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

Что умеет Массив, а чего нет

Массив хранит значения по порядку и обращается к ним по индексу, который начинается с нуля. Из методов у него есть Добавить, Вставить, Получить, Установить, Удалить, Найти, Количество, ВГраница, Очистить. Сортировки в списке нет.

Поэтому задача всегда сводится к схеме из трёх действий:

  1. Загрузить значения массива в коллекцию с сортировкой.
  2. Отсортировать её.
  3. Выгрузить значения обратно в массив.

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

Что в массивеЧем сортироватьСложность кода
Числа, строки, датыСписокЗначений4 строки
Структуры, соответствияТаблицаЗначений10–15 строк
Любые данные, особое правило порядкаручной обмен элементов15–20 строк
Данные из базыУПОРЯДОЧИТЬ ПО в запросебез массива вовсе

Простые типы: числа, строки и даты через список значений

Самый короткий путь. У СписокЗначений есть методы ЗагрузитьЗначения и ВыгрузитьЗначения, а сортировка делается по значению элемента.

Массив = Новый Массив;
Массив.Добавить(15);
Массив.Добавить(3);
Массив.Добавить(42);
Массив.Добавить(7);

Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(Массив);
Список.СортироватьПоЗначению(НаправлениеСортировки.Возрастание);
Массив = Список.ВыгрузитьЗначения();

После выполнения в массиве будет 3, 7, 15, 42. Чтобы получить порядок от большего к меньшему, замените Возрастание на Убывание: выйдет 42, 15, 7, 3.

Тот же код работает для строк (по алфавиту) и для дат (от ранней к поздней). Менять ничего не нужно.

Метод ВыгрузитьЗначения создаёт новый массив. Если на старый массив ссылается другая переменная или параметр процедуры, она по-прежнему увидит несортированные данные. Сортируйте и возвращайте результат явно или очищайте и заполняйте исходный массив заново.

Если исходный массив нужно сохранить на месте, заполните его заново:

Результат = Список.ВыгрузитьЗначения();
Массив.Очистить();
Для Каждого Элемент Из Результат Цикл
	Массив.Добавить(Элемент);
КонецЦикла;

Массив структур: сортировка через таблицу значений

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

Массив = Новый Массив;
Массив.Добавить(Новый Структура("Наименование, Сумма", "Стол", 12000));
Массив.Добавить(Новый Структура("Наименование, Сумма", "Стул", 3500));
Массив.Добавить(Новый Структура("Наименование, Сумма", "Шкаф", 27000));

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Наименование");
Таблица.Колонки.Добавить("Сумма");

Для Каждого Элемент Из Массив Цикл
	ЗаполнитьЗначенияСвойств(Таблица.Добавить(), Элемент);
КонецЦикла;

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

Массив.Очистить();
Для Каждого Строка Из Таблица Цикл
	Массив.Добавить(Новый Структура("Наименование, Сумма", Строка.Наименование, Строка.Сумма));
КонецЦикла;

Порядок после сортировки: шкаф (27000), стол (12000), стул (3500).

Строка в Сортировать состоит из имён колонок и необязательного направления: Возр или Убыв. Колонок может быть несколько через запятую:

Таблица.Сортировать("Наименование Возр, Сумма Убыв");

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

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

Для массива соответствий схема та же: ключи соответствия становятся колонками.

Ручная сортировка: обмен соседних элементов

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

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

Процедура СортироватьМассивОбменом(Массив)
	Граница = Массив.ВГраница();
	Для Внешний = 0 По Граница - 1 Цикл
		БылОбмен = Ложь;
		Для Внутренний = 0 По Граница - Внешний - 1 Цикл
			Если Массив[Внутренний] > Массив[Внутренний + 1] Тогда
				Буфер = Массив[Внутренний];
				Массив[Внутренний] = Массив[Внутренний + 1];
				Массив[Внутренний + 1] = Буфер;
				БылОбмен = Истина;
			КонецЕсли;
		КонецЦикла;
		Если Не БылОбмен Тогда
			Прервать;
		КонецЕсли;
	КонецЦикла;
КонецПроцедуры

Массив передаётся в процедуру по ссылке, поэтому после вызова исходный массив уже отсортирован. Флаг БылОбмен позволяет выйти раньше: если за проход не поменялось ничего, дальше смотреть нечего.

Прогоним мысленно на массиве 5, 2, 9, 1. Граница равна 3. Первый внешний проход: пара 5, 2 меняется, получаем 2, 5, 9, 1; пара 5, 9 остаётся; пара 9, 1 меняется, получаем 2, 5, 1, 9. Второй проход переставит 5 и 1: 2, 1, 5, 9. Третий — 1, 2, 5, 9. Готово.

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

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

Как ведут себя разные типы при сравнении

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

В 1С можно сравнить на «больше/меньше» числа с числами, строки со строками, даты с датами. А вот пара «число и строка» при операторе > в ручной сортировке вызовет ошибку исполнения. При сортировке через список или таблицу значений ошибки может не быть, но порядок будет определён внутренним правилом платформы для разных типов. Опираться на него не стоит.

Что делать на практике:

  • 🔢 Приведите всё к одному типу до сортировки. Числа, записанные строками, переведите функцией Число(Строка), предварительно проверив её через ТипЗнч.
  • 📅 Даты храните как даты, а не как текст "05.03.2026". Строки сортируются посимвольно, и "10.01.2026" окажется раньше "05.03.2026".
  • 🔤 Числа в виде строк тоже сортируются посимвольно: "100" встанет перед "20". Если нужен числовой порядок, переводите значения в число.
  • ⚪ Пустые значения (Неопределено, Null, пустая строка) лучше убрать из массива заранее или заменить явным значением.

Простая защита перед сортировкой — пройти по массиву и проверить типы:

Для Каждого Элемент Из Массив Цикл
	Если ТипЗнч(Элемент) <> Тип("Число") Тогда
		ВызватьИсключение "В массиве есть нечисловое значение: " + Строка(Элемент);
	КонецЕсли;
КонецЦикла;

Типовые задачи после сортировки

Отсортированный массив редко нужен сам по себе. Обычно за сортировкой идёт ещё одно действие, и часть из них решается теми же инструментами.

Убрать дубли и упорядочить

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

Список = Новый СписокЗначений;
Список.ЗагрузитьЗначения(Массив);
Список.СортироватьПоЗначению(НаправлениеСортировки.Возрастание);

Результат = Новый Массив;
Для Каждого Элемент Из Список Цикл
	Если Результат.Найти(Элемент.Значение) = Неопределено Тогда
		Результат.Добавить(Элемент.Значение);
	КонецЕсли;
КонецЦикла;

Для массива 4, 1, 4, 2, 1 получится 1, 2, 4. Метод Найти просматривает массив целиком, поэтому на очень больших массивах быстрее вести отдельное соответствие по ключам. На типичных объёмах (до нескольких тысяч элементов) разницы не заметите.

Развернуть порядок

Иногда нужно просто перевернуть массив, не сравнивая значения. Для этого сортировка не нужна: достаточно пройти с конца и заполнить новый массив.

Перевёрнутый = Новый Массив;
Для Сч = 1 По Массив.Количество() Цикл
	Перевёрнутый.Добавить(Массив[Массив.Количество() - Сч]);
КонецЦикла;

Для 10, 20, 30 результат — 30, 20, 10. Это не то же самое, что сортировка по убыванию: перевернётся любой порядок, в том числе неупорядоченный.

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

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

Таблица = Новый ТаблицаЗначений;
Таблица.Колонки.Добавить("Текст");
Таблица.Колонки.Добавить("Длина");

Для Каждого Элемент Из Массив Цикл
	Строка = Таблица.Добавить();
	Строка.Текст = Элемент;
	Строка.Длина = СтрДлина(Элемент);
КонецЦикла;

Таблица.Сортировать("Длина Возр, Текст Возр");
Массив = Таблица.ВыгрузитьКолонку("Текст");

Короткие строки идут первыми, а строки одинаковой длины упорядочены по алфавиту. Такой приём заменяет ручной обмен с собственным правилом сравнения почти во всех случаях и читается проще.

Поиск в отсортированных данных

Массив после сортировки удобен для бинарного поиска, но метод Найти в 1С просто перебирает элементы подряд, порядок ему не помогает. Если нужен быстрый поиск по большому набору значений, лучше собрать соответствие, где значение является ключом.

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

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

СпособКогда использоватьМинусы
Список значенийПростые типы, любой размерНе умеет сортировать по полям структуры
Таблица значенийСтруктуры, несколько полей, смешанные направленияБольше кода и памяти
Ручной обменНестандартное правило, малые массивыКвадратичный рост времени
Запрос с УПОРЯДОЧИТЬ ПОДанные берутся из базыНужен запрос, не подходит для готового массива

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

Когда массив вообще не нужен

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

Запрос = Новый Запрос;
Запрос.Текст =
	"ВЫБРАТЬ
	|	Номенклатура.Наименование КАК Наименование
	|ИЗ
	|	Справочник.Номенклатура КАК Номенклатура
	|
	|УПОРЯДОЧИТЬ ПО
	|	Наименование";
Массив = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Наименование");

Массив получится уже упорядоченным по наименованию. Для убывания добавьте УБЫВ после имени поля. Сортировку в запросе делает СУБД, и это обычно эффективнее, чем выгружать всё в клиентский или серверный код.

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

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

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

Есть ли у массива метод Сортировать в 1С 8.3?
Нет. Массив сортируют через список значений (СортироватьПоЗначению), таблицу значений (Сортировать) или собственной процедурой.
Как отсортировать массив по убыванию?
В списке значений укажите НаправлениеСортировки.Убывание. В таблице значений добавьте к имени колонки слово Убыв, например "Сумма Убыв".
Почему строки с числами сортируются неправильно?
Строки сравниваются посимвольно, поэтому "100" идёт раньше "20". Переведите значения в число перед сортировкой.
Меняет ли сортировка списка значений исходный массив?
Нет. ЗагрузитьЗначения копирует данные, а ВыгрузитьЗначения создаёт новый массив. Присвойте результат переменной или заполните исходный массив заново.
Можно ли отсортировать массив на клиенте без обращения к серверу?
Да. Список значений и таблица значений доступны в клиентском коде, так что вызов сервера для сортировки не нужен.