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