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