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

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

Как отсортировать массив в 1С: рабочие способы с примерами кода

Способы сортировки массива в 1С: через СписокЗначений, ТаблицуЗначений и пузырьковый алгоритм. Готовые примеры кода, сравнение методов и разбор типичных ошибок.

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

Выбор способа зависит от трёх факторов: какого типа элементы хранятся в массиве, нужно ли сортировать по нескольким критериям и насколько критична производительность. Для массива из примитивных значений (числа, строки, даты) проще всего подходит СписокЗначений. Для массива структур или сортировки по нескольким полям удобнее ТаблицаЗначений. Ручной алгоритм оправдан только в особых случаях.

Ниже разобраны все три подхода с готовым кодом, который можно скопировать в конфигуратор и адаптировать под свою задачу, а также сравнение методов и разбор типичных ошибок.

Почему у массива в 1С нет метода сортировки

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

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

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

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

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

Функция ОтсортироватьМассив(ИсходныйМассив) Экспорт

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

Список.ЗагрузитьЗначения(ИсходныйМассив);

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

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

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

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

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

Порядок действий
  1. 1
    Создайте объект СписокЗначений
  2. 2
    Загрузите в него элементы массива методом ЗагрузитьЗначения()
  3. 3
    Вызовите СортироватьПоЗначению() с нужным направлением
  4. 4
    Выгрузите результат обратно в массив методом ВыгрузитьЗначения()
  5. 5
    Проверьте порядок элементов в отладчике или через Сообщить()

Способ 2: сортировка через ТаблицуЗначений

Когда массив содержит структуры или сортировать нужно по нескольким критериям, СписокЗначений уже не справится. В этом случае данные переносятся в ТаблицуЗначений, где метод Сортировать() принимает строку с перечнем колонок и направлений, например "Дата Возр, Сумма Убыв".

Пример: есть массив структур с полями «Контрагент» и «Сумма», нужно отсортировать по убыванию суммы.

Процедура ОтсортироватьПоСумме(МассивДанных)

Таблица = Новый ТаблицаЗначений;

Таблица.Колонки.Добавить("Контрагент");

Таблица.Колонки.Добавить("Сумма", Новый ОписаниеТипов("Число"));

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

Строка = Таблица.Добавить();

ЗаполнитьЗначенияСвойств(Строка, Элемент);

КонецЦикла;

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

КонецПроцедуры

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

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

Способ 3: ручной алгоритм сортировки

Иногда промежуточные коллекции не подходят: например, правило сравнения нестандартное (сортировка по длине строки, по произвольному реквизиту ссылки) или нужно отсортировать массив «на месте» без создания новых объектов. Тогда алгоритм пишется вручную. Классический вариант — пузырьковая сортировка:

Процедура СортироватьПузырьком(Массив)

Для Инд = 0 По Массив.ВГраница() - 1 Цикл

Для Ж = 0 По Массив.ВГраница() - 1 - Инд Цикл

Если Массив[Ж] > Массив[Ж + 1] Тогда

Временное = Массив[Ж];

Массив[Ж] = Массив[Ж + 1];

Массив[Ж + 1] = Временное;

КонецЕсли;

КонецЦикла;

КонецЦикла;

КонецПроцедуры

Для нестандартного правила сравнения достаточно заменить условие Массив[Ж] > Массив[Ж + 1] на собственное, например СтрДлина(Массив[Ж]) > СтрДлина(Массив[Ж + 1]). Это главное преимущество ручного подхода — полный контроль над логикой сравнения.

Минус очевиден: пузырьковая сортировка имеет квадратичную сложность и на больших массивах (тысячи элементов) будет заметно медленнее штатных методов коллекций. Для объёмных данных лучше реализовать быструю сортировку рекурсией или всё же переложить данные в ТаблицуЗначений.

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

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

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

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

Что выбрать

СписокЗначений

Массив чисел, строк, дат или ссылок одного вида. Самый быстрый в написании вариант, но только один критерий сортировки.

ТаблицаЗначений

Массив структур или нужна сортировка по нескольким полям с разным направлением. Требует явного описания типов колонок.

Ручной алгоритм

Нестандартное правило сравнения или запрет на создание промежуточных объектов. Медленно на больших объёмах.

Альтернатива: упорядочивание на уровне запроса

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

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

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

"ВЫБРАТЬ

| Номенклатура.Ссылка КАК Ссылка

|ИЗ

| Справочник.Номенклатура КАК Номенклатура

|УПОРЯДОЧИТЬ ПО

| Номенклатура.Наименование";

МассивСсылок = Запрос.Выполнить().Выгрузить().ВыгрузитьКолонку("Ссылка");

Дополнительное преимущество — конструкция АВТОУПОРЯДОЧИВАНИЕ, которая сортирует ссылочные данные по естественному порядку (справочники по наименованию, документы по дате и номеру). Если источник массива — запрос, всегда проверяйте, нельзя ли решить задачу сортировки прямо в его тексте.

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

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

Предыдущее = Неопределено;

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

Если Предыдущее <> Неопределено И Элемент < Предыдущее Тогда

Сообщить("Нарушение порядка: " + Элемент);

КонецЕсли;

Предыдущее = Элемент;

КонецЦикла;

Чаще всего проблемы возникают не из-за самой сортировки, а из-за данных. Смешанные типы в массиве (числа и строки вперемешку) дают порядок, который выглядит случайным: платформа сравнивает значения по внутренним правилам приведения типов. Строки с числами сортируются лексикографически — «10» окажется раньше «2», потому что сравнение идёт посимвольно.

Ещё одна частая ситуация — попытка отсортировать массив структур через СписокЗначений. Структуры между собой не сравниваются операторами «больше/меньше», и сортировка либо выдаст ошибку, либо непредсказуемый результат. Для структур используйте только ТаблицуЗначений или ручной алгоритм.

Типичные ошибки
01
Вызов несуществующего метода Массив.Сортировать() — получите ошибку «Метод объекта не обнаружен»; используйте промежуточную коллекцию
02
Сортировка строк с числами без приведения к числу — «10» встаёт раньше «2», порядок выглядит неверным
03
Колонка таблицы значений без указания типа — числа сортируются некорректно при смешанных данных
04
Попытка отсортировать массив структур через СписокЗначений — структуры несравнимы, результат непредсказуем
05
Забытое направление сортировки — по умолчанию СортироватьПоЗначению() без параметра сортирует по возрастанию, что не всегда ожидается
Контрольные точки

Как проверить результат

Порядок элементов после сортировки
Норма

Каждый следующий элемент не меньше предыдущего (при сортировке по возрастанию)

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

Встречаются пары, где порядок нарушен

Числовые значения в массиве
Норма

2 стоит раньше 10

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

10 стоит раньше 2 — значит, данные сравниваются как строки

Типы элементов массива
Норма

Все элементы одного сравнимого типа

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

Смесь чисел, строк и ссылок — порядок непредсказуем

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

Можно ли отсортировать массив в 1С одной строкой кода?

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

Как отсортировать массив по убыванию?

При использовании СпискаЗначений передайте в метод СортироватьПоЗначению() параметр НаправлениеСортировки.Убыв. В ТаблицеЗначений укажите «Убыв» после имени колонки в строке сортировки, например Таблица.Сортировать("Сумма Убыв"). В ручном алгоритме просто поменяйте знак сравнения с «больше» на «меньше».

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

СписокЗначений здесь не поможет — структуры не сравниваются между собой. Перенесите данные в ТаблицуЗначений с колонками под нужные ключи и вызовите Сортировать() по нужной колонке. Альтернатива — ручной алгоритм, где условие сравнения обращается к ключу структуры, например Массив[Ж].Сумма > Массив[Ж + 1].Сумма.

Что быстрее: сортировка в запросе или сортировка массива в коде?

Упорядочивание в запросе почти всегда быстрее, потому что выполняется на стороне СУБД с использованием индексов. Если данные для массива берутся из базы, добавляйте УПОРЯДОЧИТЬ ПО в текст запроса. Сортировку коллекций в коде оставляйте для случаев, когда массив получен не из запроса или порядок определяется логикой, недоступной в запросе.

Почему числа в массиве сортируются в неправильном порядке?

Скорее всего, элементы массива на самом деле строки, а не числа. Строки сравниваются посимвольно, поэтому «10» оказывается раньше «2». Приведите значения к числу функцией Число() при заполнении массива или укажите числовой тип колонки при сортировке через ТаблицуЗначений — после этого порядок станет корректным.

Можно ли отсортировать массив ссылок на документы по дате?

Да, но не через СписокЗначений — ссылки сортируются по внутреннему представлению, а не по дате. Используйте запрос с УПОРЯДОЧИТЬ ПО по полю Дата, передав массив ссылок в параметр и отфильтровав по условию В(&МассивСсылок), либо выгрузите ссылки в ТаблицуЗначений с колонкой даты, заполнив её из реквизита ссылки.

Итог

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

У массива в 1С нет метода сортировки. Для простых значений используйте СписокЗначений с СортироватьПоЗначению(), для структур и нескольких критериев — ТаблицуЗначений с Сортировать(), а данные из базы упорядочивайте прямо в запросе. Всегда контролируйте типы элементов: строки с числами сортируются посимвольно.