Сортируем ДанныеФормыДерево на клиенте

10.09.20

Разработка - Работа с интерфейсом

Иногда так хочется, но нечем...

 

У ДанныеФормыКоллекция для сортировки есть специальный метод Сортировать(). Он доступен на клиенте и, хоть и делает вызов сервера, но, по понятным причинам, срабатывает крайне быстро.

 

А вот ДанныеФормыДерево платформа обделила такой возможностью. Вместо этого программисты обычно переходят «на сервер», преобразуют ДанныеФормыДерево в полноценное ДеревоЗначений, сортируют и преобразуют обратно.

 

ДеревоЗначений    = ДанныеФормыВЗначение(ДанныеФормыДерево, Тип("ДеревоЗначений")); 
ДеревоЗначений.Строки.Сортировать("КолонкиСортировки", Истина); 
ЗначениеВДанныеФормы(ДанныеФормыДерево, ДеревоЗначений);

 

А ведь существуют ситуации, когда перебрасывать данные всей формы «на сервер» значительно затратнее, чем, оставаясь «на клиенте», отсортировать десяток строчек.

 

Для реализации Менеджер открытых форм опробовал разные алгоритмы сортировки ДанныеФормыДерево, доступные на клиенте. В результате, остановился на этом, что помогло ускорить открытие формы обработки в 2,5 раза.

 

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

 

 

P.S.: Есть альтернативные варианты процедуры? Выкладывайте в комментариях. Если наберётся достаточное количество интересных методов, то после можем провести нагрузочное тестирование, выложить результаты сравнения и выбрать процедуру-победитель.

 

 

&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыДерево(КоллекцияСортировки, КолонкаСортировки, ВключатьПодчиненные = Ложь)
	
	КоллекцияСтрок  = КоллекцияСортировки.ПолучитьЭлементы();
	
	СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки);
	
	Если ВключатьПодчиненные Тогда
		Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
			СортироватьДанныеФормыДерево(ТекущаяСтрока, КолонкаСортировки, ВключатьПодчиненные);
		КонецЦикла;
	КонецЕсли;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки)
	
	ПараметрыЗначений     = Новый Соответствие;
	СортированныеЗначения = Новый СписокЗначений;
	
	Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
		
		ТекущееЗначение = ТекущаяСтрока[КолонкаСортировки];
		
		ПараметрыЗначения = ПараметрыЗначений.Получить(ТекущееЗначение);
		Если ПараметрыЗначения = Неопределено Тогда
			ПараметрыЗначения = Новый Массив;
			ПараметрыЗначений.Вставить(ТекущееЗначение, ПараметрыЗначения);
			СортированныеЗначения.Добавить(ТекущееЗначение);
		КонецЕсли;
		
		ПараметрыЗначения.Добавить(ТекущаяСтрока);
		
	КонецЦикла;
	
	СортированныеЗначения.СортироватьПоЗначению(НаправлениеСортировки.Возр);
	
	
	НовыйИндекс = 0;
	Для Каждого ТекущееЗначение Из СортированныеЗначения Цикл
		
		МассивСтрок = ПараметрыЗначений.Получить(ТекущееЗначение.Значение);
		Для Каждого ТекущаяСтрока Из МассивСтрок Цикл
			
			ТекущийИндекс = КоллекцияСтрок.Индекс(ТекущаяСтрока);
			ШагСдвига     = НовыйИндекс - ТекущийИндекс;
			Если НЕ ШагСдвига = 0 Тогда
				КоллекцияСтрок.Сдвинуть(ТекущийИндекс, ШагСдвига);
			КонецЕсли;
			
			НовыйИндекс   = НовыйИндекс + 1;
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры

 

УФ Сортировка Дерево ДанныеФормыДерево

См. также

Работа с интерфейсом Рабочее место Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Платные (руб)

Богатый редактор картинок 1С предназначен для обработки изображений в режиме «Предприятие», с возможностью РИСОВАТЬ на них. Поддерживается работа как в обычных формах (толстый клиент) так и на управляемых формах (тонкий клиент). Обработка позволяет редактировать как картинки, хранимые в базе, так и графические файлы с диска на файловой системе. Помимо базовых функций (изменение размеров, преобразование формата, обрезание картинки, повороты и т.п.) – редактор имеет богатый набор инструментов для рисования. Доступна функция вставки изображения из буфера обмена. Объект может быть использован: на стороне клиента, на стороне сервера, из внешнего соединения. Обработка будет особенно полезна тем, кто вносит картинки в базу (изображения номенклатуры, фотографии физических лиц и т.п.). Функционал реализуется с использованием JavaScript и бесплатного ПО ImageMagick (без использования внешних компонент).

6000 руб.

16.01.2015    62985    44    59    

82

Работа с интерфейсом Программист Платформа 1С v8.3 Конфигурации 1cv8 1С:ERP Управление предприятием 2 Платные (руб)

Обработка предназначена для создания и управления дашбордами.

2400 руб.

29.06.2020    18855    26    6    

41

Работа с интерфейсом Программист Платформа 1С v8.3 Управляемые формы Конфигурации 1cv8 Россия Платные (руб)

Редактор графов в 1С - внешний отчет, который формирует графы на основе таблицы значений, используя рисунки табличного документа. Есть возможность добавления, редактирования объектов графа и выгрузки результата в таблицу значений.

1500 руб.

06.10.2020    10224    7    7    

10

WEB-интеграция Универсальные функции Механизмы платформы 1С Программист Платформа 1С v8.3 Конфигурации 1cv8 Бесплатно (free)

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

28.08.2023    14730    YA_418728146    7    

166

Пакетная печать Печатные формы Адаптация типовых решений Универсальные функции Платформа 1С v8.3 1С:ERP Управление предприятием 2 1С:Управление торговлей 11 1С:Комплексная автоматизация 2.х Россия Абонемент ($m)

Расширение для программ 1С:Управление торговлей, 1С:Комплексная автоматизация, 1С:ERP, которое позволяет распечатывать печатные формы для непроведенных документов. Можно настроить, каким пользователям, какие конкретные формы документов разрешено печатать без проведения документа.

2 стартмани

22.08.2023    3580    56    progmaster    8    

4

Работа с интерфейсом Программист Платформа 1С v8.3 Конфигурации 1cv8 Абонемент ($m)

"MVC плохо применима в 1С" - познакомьтесь с моделью состояния и, возможно, ваше мнение поменяется! Представленное решение является эволюционным развитием идеи реализации MVC для 1С. В новой версии добавлены DSL для описания модели состояния, а также параметризация свойств параметров и элементов формы.

1 стартмани

05.07.2022    5749    kalyaka    6    

33
Вознаграждение за ответ
Показать полностью
Комментарии
Подписаться на ответы Инфостарт бот Сортировка: Древо развёрнутое
Свернуть все
1. alex15650 212 18.06.19 10:57 Сейчас в теме
ДанныеФормыДерево вообще обделили, и поиск тоже хочется..
2. SeiOkami 3515 18.06.19 10:58 Сейчас в теме
(1) хорошая идея, добавлю в заметки
3. karpik666 3851 18.06.19 11:00 Сейчас в теме
На каком количестве элементов проверялась сортировка? 1С при этом не формирует неявных серверных вызовов?
4. SeiOkami 3515 18.06.19 11:25 Сейчас в теме
(3) боялись серверных вызовов, ибо используется метод Сдвинуть(), но не обнаружили ни по счётчику вызовов, ни по замеру производительности.

Проверяли так - генерили примитивную таблицу формы из рандомных чисел, а потом сортировали. Перебирали разные алгоритмы. Этим добились того, что 1000 элементов таблицы с рандомными числами диапазоном до 1000 сортируются меньше секунды. 10 000 строк с рандомом до 10 000 тратит время на сортировку ≈ 3 секунды.

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

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

Попробуем проанализировать ситуацию, если что-то интересное - будет статья.
markers; SergeRSA; acanta; +3 Ответить
5. karpik666 3851 18.06.19 11:28 Сейчас в теме
(4) то есть использовались только числа? Попробуйте такое же количество, но ссылочных элементов, очень интересно как отработает Обработка представления для этих элементов без серверных вызовов, и кэширует ли 1С все представления на клиенте для такого количества элементов
7. SeiOkami 3515 18.06.19 11:36 Сейчас в теме
(5)
Да, скорее всего не так классно будет.

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

Однако, в данном алгоритме именно сортировка используется только один раз на уровень дерева - СортироватьПоЗначению(). Метод платформенный, никаких "ручных" сравнений нет. Но потестировать нужно, интересно
8. karpik666 3851 18.06.19 11:42 Сейчас в теме
(7) это понятно, но ваш пример далек от реальности, так как вы используйте примитивные типы, то неявных серверных вызовов и не будет, но мне больше кажется, что такой вариант будет все равно вызывать метод сервера. Сам ранее пытался писать код, который максимально бы работал на клиенте, но все старания разбивались о работу самой 1С, которая фоном делала серверные вызовы для кода. которая в теории должен был исполняться только на клиенте.
9. SeiOkami 3515 18.06.19 11:47 Сейчас в теме
(8) пока что в этом алгоритме не замечено было, но Вы правы - нужно проверить на ссылочных типах.
11. SeiOkami 3515 18.06.19 12:12 Сейчас в теме +5 $m
(9)
(8)
Проверил на ссылке. Добавил ссылочную колонку в таблицу формы. Заполнил таблицу ссылками на существующие документы (выбрал первые 10 000 документов и разбросал рандомно по таблице). Сортировка заняла 4 секунды и счётчик вызовов не показал.

Скорее всего СписокЗначений.СортироватьПоЗначению() использует ГУИДы, а не представления, поэтому обращений на сервер и не требовалось
Alogy; karpik666; +2 Ответить
13. karpik666 3851 18.06.19 12:18 Сейчас в теме
(11) проблема не в самом методе сортировки, а в выводе дерева на экран, так как в ссылочном поле происходит северная обработка представления, потому и было интересно как поведет себя 1с. Спасибо, будет желание еще сам проверю работу этого метода
6. karpik666 3851 18.06.19 11:30 Сейчас в теме
(4) при личной проверке довольно часто выходит, что безконтекстная передача таблицы формы может быть дольше, чем контекстный серверный вызов, все зависит от того, какой объем информации содержится в остальных элементах, если по сравнениню с таблицей их пренебрежительно мало, то лучше контекстный вызов.
10. Evg-Lylyk 4841 18.06.19 12:12 Сейчас в теме
(0) Сталкивался с подобной проблемой, чуток анализировал вопрос понял что для большого количества строк на сервере быстрее
Описанный вариант кажется не оптимальным создает массив сдвигает, быструю сортировку пробовали?
12. SeiOkami 3515 18.06.19 12:16 Сейчас в теме
(10) пробовали с десяток разных алгоритмов, уже и не вспомню. Но остановились на этом. И заполнение списка значений здесь привело хороший прирост. Этот объект быстро сортирует.

Если у вас есть процедура быстрее, то выкладывайте. Хочется найти "самую-самую" и закрепить в статье.

Когда появится время, сделаю специальный инструмент для удобного тестирования методов сортировки. Чтобы можно было свою процедуру легко вставить и гонять по скорости
14. Infector 201 18.06.19 15:19 Сейчас в теме
Есть стандартные команды сортировки для элементов форм. Чаще всего проще обратить на них внимание пользователей и как-то закрепить на командных панелях. Если же сортировать нужно, но без участия пользователей скорее всего этот объект использован не в тему.
15. starik-2005 3087 20.06.19 12:30 Сейчас в теме
А не пробовали сортировать "нативно"? Тем же квиксортом?
19. Cyberhawk 135 15.10.20 18:41 Сейчас в теме
(15) А под "нативно" что имеется в виду?
28. kalyaka 1105 14.04.22 10:29 Сейчас в теме
(19) можно использовать разные алгоритмы сортировки, реализация на 1с рассмотрена в статье Популярные алгоритмы сортировки массивов
16. AlexBober78 21.06.19 18:46 Сейчас в теме
Что-то не выкладывают альтернативные варианты)
Вообще, какой-нибудь конкурс устроить. Пусть и символический.
И обработку общую сделать. Для теста с генерацией данных.
17. пользователь 01.11.19 16:41
Сообщение было скрыто модератором.
...
18. user1284652 01.11.19 16:43 Сейчас в теме
В общем, самая "нативная" сортировка (не без участия jQuery) у меня получилась следующим образом:
Все данные в ячейках я вношу в data-attribute, которые легализованы в HTML5. Чтобы метод sort() работал так, как мне надо -- данные привожу в к нижнему регистру и заменяю кавычки на апострофы, чтобы не возникла конфликта на уровне HTML.
20. e745030 29.07.21 17:21 Сейчас в теме
СписокЗначенийСортировки = Новый СписокЗначений;
	ДеревоДляСортировки = ДеревоСФормы.ПолучитьЭлементы();
	
	Счетчик = 0;
	Для Каждого СтрокаДерева Из ДеревоДляСортировки Цикл
		СписокЗначенийСортировки.Добавить(СтрокаДерева.ОсновнаяСистема, Счетчик);
		Счетчик = Счетчик + 1;
	КонецЦикла;
	
	СписокЗначенийСортировки.СортироватьПоЗначению();
	
	НеобходимыйНомерСтроки = 0;
	СмещениеВниз = 0;
	
	Для Каждого ЗначениеСортировки Из СписокЗначенийСортировки Цикл
		ТекущийНомерСтроки = Число(ЗначениеСортировки.Представление);
		
		Если ТекущийНомерСтроки < НеобходимыйНомерСтроки  Тогда
			ТекущийНомерСтроки = ТекущийНомерСтроки + СмещениеВниз;
		КонецЕсли;
		
		Если ТекущийНомерСтроки <> НеобходимыйНомерСтроки Тогда
			ДеревоДляСортировки.Сдвинуть(ТекущийНомерСтроки, НеобходимыйНомерСтроки - ТекущийНомерСтроки);
			
			СмещениеВниз = СмещениеВниз + 1;		
		КонецЕсли;
		
		НеобходимыйНомерСтроки = НеобходимыйНомерСтроки + 1;
	КонецЦикла;
Показать
Поручик; +1 Ответить
21. markers 277 29.12.21 12:35 Сейчас в теме
SeiOkami, огромное спасибо! Если кому совсем лень и нужна возможность изменять направление сортировки, то милости просим:
&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыДерево(КоллекцияСортировки, КолонкаСортировки, ВключатьПодчиненные = Ложь, ПоВозрастанию = Истина)
	
	КоллекцияСтрок = КоллекцияСортировки.ПолучитьЭлементы();
	
	СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки, ПоВозрастанию);
	
	Если ВключатьПодчиненные Тогда
		
		Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
			
			СортироватьДанныеФормыДерево(ТекущаяСтрока, КолонкаСортировки, ВключатьПодчиненные, ПоВозрастанию);
			
		КонецЦикла;
		
	КонецЕсли;
	
КонецПроцедуры

&НаКлиентеНаСервереБезКонтекста
Процедура СортироватьДанныеФормыКоллекция(КоллекцияСтрок, КолонкаСортировки, ПоВозрастанию = Истина)
	
	ПараметрыЗначений     = Новый Соответствие;
	СортированныеЗначения = Новый СписокЗначений;
	
	Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
		
		ТекущееЗначение = ТекущаяСтрока[КолонкаСортировки];
		
		ПараметрыЗначения = ПараметрыЗначений.Получить(ТекущееЗначение);
		
		Если ПараметрыЗначения = Неопределено Тогда
			
			ПараметрыЗначения = Новый Массив;
			ПараметрыЗначений.Вставить(ТекущееЗначение, ПараметрыЗначения);
			СортированныеЗначения.Добавить(ТекущееЗначение);
			
		КонецЕсли;
		
		ПараметрыЗначения.Добавить(ТекущаяСтрока);
		
	КонецЦикла;
	
	СортированныеЗначения.СортироватьПоЗначению(?(ПоВозрастанию, НаправлениеСортировки.Возр, НаправлениеСортировки.Убыв));
	НовыйИндекс = 0;
	
	Для Каждого ТекущееЗначение Из СортированныеЗначения Цикл
		
		МассивСтрок = ПараметрыЗначений.Получить(ТекущееЗначение.Значение);
		
		Для Каждого ТекущаяСтрока Из МассивСтрок Цикл
			
			ТекущийИндекс = КоллекцияСтрок.Индекс(ТекущаяСтрока);
			ШагСдвига     = НовыйИндекс - ТекущийИндекс;
			
			Если НЕ ШагСдвига = 0 Тогда
				
				КоллекцияСтрок.Сдвинуть(ТекущийИндекс, ШагСдвига);
				
			КонецЕсли;
			
			НовыйИндекс = НовыйИндекс + 1;
			
		КонецЦикла;
		
	КонецЦикла;
	
КонецПроцедуры
Показать

Ну и в друг, кому будет нужно: Интерактивный отбор в дереве
22. TimurD 6 31.03.22 09:40 Сейчас в теме
Самому как-то понадобилось использовать методы Найти и НайтиСтроки на клиенте у дерева. Реализовал алгоритм (по итогу сравнивал структуры), но на практике выяснил, что при большом дереве (от 1000 элементов примерно) производительность проседала. Сортировки и отборы на клиенте вещь, конечно хорошая, но если там данных немного. В остальных случаях лучше ходить на сервер, типа выбираем меньшее из зол.
23. Aleksey_Abramov 04.04.22 12:34 Сейчас в теме
Работает. Вставил в свой код. Плюсую. Но мне не понятно, как это работает? Уже нервничать начинаю.
Объясните кусок кода:
Для Каждого ТекущаяСтрока Из КоллекцияСтрок Цикл
		
		ТекущееЗначение = ТекущаяСтрока[КолонкаСортировки];
		
		ПараметрыЗначения = ПараметрыЗначений.Получить(ТекущееЗначение);
		Если ПараметрыЗначения = Неопределено Тогда
			ПараметрыЗначения = Новый Массив;
			ПараметрыЗначений.Вставить(ТекущееЗначение, ПараметрыЗначения);
			СортированныеЗначения.Добавить(ТекущееЗначение);
		КонецЕсли;
		
		ПараметрыЗначения.Добавить(ТекущаяСтрока);
		
	КонецЦикла;
Показать

Для чего здесь массив ПараметрыЗначения? Он ведь постоянно создаётся новый. Потом вставляется в ПараметрыЗначений этот пустой массив, а только потом в него добавляется элемент. И опять новый массив. Мне кажется тут что-то лишнее. Если нет, объясните, что в нём и зачем он в дальнейшем?
24. SeiOkami 3515 04.04.22 12:42 Сейчас в теме
(23)
Он создаётся новый для каждого уникального значения колонки. Т.е., если в коллекции будет 100 строк с одинаковым значением колонки, то массив будет создан один раз и наполнен этими 100 строками.
25. Aleksey_Abramov 04.04.22 13:06 Сейчас в теме
(24) В моём случае разные строки. Но непонятно, зачем создаётся этот массив, потом он пустым вставляется в соответствие, а только потом в массив добавляется значение и он потом затирается. Или если добавить массив в соответствие, а потом в массив добавить элемент. То и в соответствии этот массив изменится? Думаю понятно выразил мысль)
26. SeiOkami 3515 04.04.22 13:27 Сейчас в теме
(25)
Или если добавить массив в соответствие, а потом в массив добавить элемент

Ага, именно так)

Мы создаём массив. И 1С размещает его где-то в памяти, а нам в переменную отдаёт ссылку на массив.
Мы эту ссылку помещаем в соответствие. И если где-то в коде (где угодно) мы этот массив изменим, то и в соответствии он изменится. Потому что там лежит ссылка на оригинал, который мы меняем (так же по ссылке).
Aleksey_Abramov; +1 Ответить
27. Aleksey_Abramov 10.04.22 17:37 Сейчас в теме
(26) Спасибо за ответы на мои странные вопросы) Разобрался.
SeiOkami; +1 Ответить
29. kalyaka 1105 14.04.22 10:56 Сейчас в теме
Предлагаю свой вариант решения на основе реализации абстрактных алгоритмов
В функциональном стиле:
ОтсортированныеЭлементыДерева = атдМассив
	.Массив(ЭлементыДерева)
	.СортироватьПо("Наименование")
	.ВМассив()
;
В процедурном:
ОтсортированныеЭлементыДерева = ОбщегоНазначенияКлиентСервер.СкопироватьМассив(ЭлементыДерева);
РаботаСМассивом.СортироватьПо(ОтсортированныеЭлементыДерева, "Наименование");
Пример можно посмотреть в демо базе
30. SeiOkami 3515 14.04.22 11:42 Сейчас в теме
(29)страница не найдена
Прикрепленные файлы:
31. kalyaka 1105 14.04.22 12:03 Сейчас в теме
(30) по всей видимости нужна регистрация на github. Еще демо-база прикреплена к статье Работа с абстрактным массивом
32. SeiOkami 3515 14.04.22 12:13 Сейчас в теме
(31) авторизовался
Всё равно 404)
Прикрепленные файлы:
33. kalyaka 1105 14.04.22 12:56 Сейчас в теме
(32)Извините, я оказывается не перевел релиз в publlish. Попробуйте теперь.
Если что, то вот ссылка на релиз https://github.com/KalyakinAG/adt-array/releases/tag/v1.0.5
35. SeiOkami 3515 21.04.22 17:12 Сейчас в теме
(29) посмотрел, интересный подход. Но, к сожалению, это будет работать однозначно намного медленнее хотя бы из-за создания объекта формы\обработки и использования Выполнить(""). А выложенная в посте функция сделана специально для быстрой сортировки на клиенте.
36. kalyaka 1105 21.04.22 19:19 Сейчас в теме
(35)Ну объект там создается один раз при открытии формы и далее используется неограниченное количество раз.

В процедурном варианте объект вообще не создается.

Вместо Выполнить() используется Вычислить(). Разница не только в том, что вторая использует выражение, но и в том, что Вычислить() работает на всех клиентах в отличии от Выполнить().

Пожертвовав универсальностью можно заменить Вычислить() на функцию "Сравнить(А.Наименование, Б.Наименование)", быстродействие процентов на 20% примерно прибавится.
Вот что у меня получилось для двух алгоритмов: нативный и ваш:
---
Вариант нативно 2: 13 мс
Вариант нативно 2: 12 мс
Вариант нативно 2: 9 мс
Вариант нативно 2: 9 мс
Вариант нативно 2: 8 мс
Вариант список значений: 10 мс
Вариант список значений: 12 мс
Вариант список значений: 13 мс
Вариант список значений: 13 мс
Вариант список значений: 10 мс
---
Функция Сравнить(А, Б)
	Если А = Б Тогда
		Возврат 0;
	КонецЕсли;
	Если А < Б Тогда
		Возврат -1;
	КонецЕсли;
	Возврат 1;
КонецФункции
Показать

Видно, что мой алгоритм даже работает быстрее. В моем алгоритме нет лишнего преобразования в массив, а алгоритм сортировки использован "Быстрая сортировка" (в платформе скорее всего такой же).

Но, здесь я использовал жестко заданное поле "Наименование" (можно любое другое, важно, что в алгоритме оно жестко прописывается). Поле можно передавать в функцию, тогда вызов будет "Сравнить(А[Поле], Б[Поле])" - скорость почти прежняя.

Ок, можно расширить количество полей сортировки, для этого нужно заменить на функцию СравнитьПо(А, Б, Поля). Вот что у меня получилось для полей сортировки "ВидНоменклатуры, Наименование":
---
Вариант нативно 3: 9 мс
Вариант нативно 3: 15 мс
Вариант нативно 3: 15 мс
Вариант нативно 3: 15 мс
Вариант нативно 3: 15 мс
---
Функция СравнитьПо(А, Б, Поля)
	Для Каждого Поле Из СтрРазделить(Поля, ", ", Ложь) Цикл
		Результат = Сравнить(А[Поле], Б[Поле]);
		Если Результат < 0 Тогда
			Возврат -1;
		ИначеЕсли Результат > 0 Тогда
			Возврат 1;
		КонецЕсли;
	КонецЦикла;
	Возврат 0;
КонецФункции
Показать

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

К этому посту прикреплена демо-обработка, запускать в демо-базе.
Прикрепленные файлы:
_ДемоАТДМассив.epf
37. kalyaka 1105 21.04.22 21:10 Сейчас в теме
(36)Исправил в обработке неточность: Вариант Нативно 3 (по полю), Вариант Нативно 4 (по нескольким полям). Типы дополнительных полей привел к простым, т.к. сортировка по составным полям будет явно проседать (практически запрос в цикле получится).
Прикрепленные файлы:
_ДемоАТДМассив.epf
38. kalyaka 1105 22.04.22 17:48 Сейчас в теме
(35)
сделана специально для быстрой сортировки на клиенте
Кстати все предложенные мной алгоритмы работают на клиенте без обращения на сервер, даже объектный вариант.
34. kalyaka 1105 18.04.22 19:52 Сейчас в теме
Добавил еще два варианта:

с использованием приоритетной очереди
ОтсортированныеЭлементыДерева = Новый Массив;
Для Каждого ЭлементДерева Из ЭлементыДерева Цикл
	РаботаСМассивом.ПоложитьВОчередьСПриоритетом(ОтсортированныеЭлементыДерева, ЭлементДерева, "Сравнить(А.Наименование, Б.Наименование)");
КонецЦикла;
нативный
&НаКлиенте
Процедура СортироватьЭлементыНативно(Элементы, ВыражениеПредиката, НижнийПредел, ВерхнийПредел)
    Начало = НижнийПредел;
    Конец = ВерхнийПредел;
    Б = Элементы[Цел((Начало + Конец)/2)];
    Пока Истина Цикл
        А = Элементы[Начало];
        Пока Вычислить(ВыражениеПредиката) < 0 Цикл // Элементы[Начало] < Б
            Начало = Начало + 1;                   
            А = Элементы[Начало];
        КонецЦикла;
        А = Элементы[Конец];
        Пока Вычислить(ВыражениеПредиката) > 0 Цикл // Элементы[Конец] > Б
            Конец = Конец - 1;                   
            А = Элементы[Конец];
        КонецЦикла; 
        Если Начало <= Конец Тогда               
            //  Дерево значений
            //  Начало -> Конец
            //  Конец -> Начало 
            
            ШагСдвига = Конец - Начало;
            Если НЕ ШагСдвига = 0 Тогда
                Элементы.Сдвинуть(Начало, ШагСдвига);
                ШагСдвига = ШагСдвига - 1;
                Если НЕ ШагСдвига = 0 Тогда
                    Элементы.Сдвинуть(Конец - 1, -ШагСдвига);
                КонецЕсли;
            КонецЕсли;
            
            //  Дерево значений            
            Начало = Начало + 1;
            Конец = Конец - 1;            
        КонецЕсли;
        Если Начало > Конец Тогда                       
            Прервать;                        
        КонецЕсли;
    КонецЦикла;
    Если НижнийПредел < Конец Тогда         
        СортироватьЭлементыНативно(Элементы, ВыражениеПредиката, НижнийПредел, Конец);        
    КонецЕсли; 
    Если Начало < ВерхнийПредел Тогда                      
        СортироватьЭлементыНативно(Элементы, ВыражениеПредиката, Начало, ВерхнийПредел);        
    КонецЕсли;
    
КонецПроцедуры
Показать
Скачать демо можно из статьи или из github
Оставьте свое сообщение