Перенос произвольного количества элементов на новую позицию в нумерованном списке

Алгоритм перемещения позиций в нумерованном списке одним запросом.

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

Возможно я изобретаю велосипед и не умею в поиск, но подходящих мне вариантов не нашел. Публикую свой вариант решения.

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

Размещать позиции считаю правильным перед элементом (корень, k) на который мы "сбрасываем"  выделенные элементы , и алгоритм я буду строить для такого варианта.

Что нужно определить в первую очередь? Диапазон, который затрагивает перемещение, поскольку  при переносе элементов затрагиваются только позиции лежащие между минимальным номером min(nk)в списке перемещения K (корень тоже учитываем) и максимальным max(nk). Для остальных позиций нумерация не меняется.

Вторым шагом необходимо выстроить по возрастанию список выделенных для переноса элементов, поскольку  выделение может происходить не по порядку следования элементов. Делается это через объединение таблицы переносимых элементов с самой собой и подсчетом количества позиций лежащих ниже вычисляемой sum(nk<n). Для больших списков  квадратичная трудоемкость алгоритма нумерации будет влиять сильно, но вряд ли кто в здравом уме будет одновременно переносить больше сотни выделенных элементов, поэтому трудоемкостью пренебрегаем.

Третий шаг — вычисление смещения переносимых элементов относительно корня sum(nk<K)(например если корень=11, а переносим 8,9, 12, 13 и 15, смещение будет 2 или количество элементов стоящих по порядку ниже корня). Смещение укажет нижний диапазон, с которого начнется новая нумерация перенесенных элементов. В объединенном запросе эти шаги будут идти не по порядку, я показываю ход мысли при решении задачи.

Четвертый шаг — вычисление множества "неподвижных" элементов Е ={min(nk)<=n<max(nk)}K и смещение их на количество позиций, появившихся в результате перемещения . Решается с помощью соединения с таблицей перемещаемых элементов. При соединении подсчитывается сколько перемещаемых позиций стоят ниже элементов которые сами ниже корня sum(nk<ne|ne<k) и соответственно количество стоящих выше для элементов выше корня sum(nk>ne|ne>k). Это будет индивидуальное смещение для каждого "неподвижного" элемента в диапазоне.

Запрос готов:

 

Теперь в списке нужно прописать процедуры перетаскивания:

 

Готово. Можно перетаскивать выделенные элементы в любом количестве с любой позиции.

Leave a Comment

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