Перейти к содержимому

Фото
- - - - -

Сортировка объектов


  • Вы не можете создать новую тему
  • Please log in to reply
12 ответов в этой теме

#1 StrikeR

StrikeR

    бугога

  • Постоялец
  • 798 сообщений
  • Откуда:QLD. Australia

Отправлено 16 мая 2008 - 02:38

Делаю штуку дрюку одну на флеше. Имеется таблица в базе данных с id номером объекта и с его названием, что-то типа:
1 data1
2 data2
3 data3
4 data4
5 data5

во флеше имеется возможность перетаскивать (обчный drag'n'drop) объекты, например, перетаскиваю объект 'data4' между 1-ым и 2-ым объектом, получается, в базе данных данные должны тоже поменяться местами, в итоге получится в ней такое:
1 data1
4 data4
2 data2
3 data3
5 data5

Вопрос собсна как мне это сделать (т.е. что такого умного напичать в php), если я знаю id перетаскиваемого объекта и id объекта после которого (или перед которым) он должен следовать?

Сообщение изменено: StrikeR (16 мая 2008 - 02:38 )

  • 0

#2 Lynx

Lynx
  • Пользователь
  • 162 сообщений
  • Откуда:Таллинн

Отправлено 16 мая 2008 - 04:45

а в чем собственно проблема?
есть какой-то конкретный вопрос или тебя интересует как это в принципе возможно сделать? т.е. есть ли у тебя уже какой-то код, и где в нем что-то не работает?
  • 0

#3 StrikeR

StrikeR

    бугога

  • Постоялец
  • 798 сообщений
  • Откуда:QLD. Australia

Отправлено 16 мая 2008 - 16:36

интересует именно момент, как сделать эту сортировку. Например что-то типа функции: myfunc(id1, id2), где id1 - ид номер перетаскиваемого объекта, id2 - ид номер объекта перед которым в базе встанет id1.
  • 0

#4 ParadoxL

ParadoxL
  • Постоялец
  • 5 023 сообщений
  • Откуда:Edinburg

Отправлено 16 мая 2008 - 17:49

StrikeR, если в базе (подразумевается релиционная база данных) ... то можно сделать дополнительное поле position ... которое будет отвечать за позицию каждого объекта (строки) ...
Тут два варианта ...
1. при замене делаешь переиндексациою position у всех в интервале между заменяемым и последним элементом.
2. position объявляешь как decimal (float, double ... ) и при перестановки позиции ... делаешь position[new] = (position[n]+position[n+1])/2

например ...
idx | 	value | pos
1	a	1
2	b	10
3	c	20
4	d	30
5	e	40
тебе надо перетащить d между a и b ...
получается pos[d] = (pos[a] + pos[b]) /2 = (1 + 10)/2 =5.5
имеем ...
idx | 	value | pos
1	a	1
4	d	5.5
2	b	10
3	c	20
5	e	40

и так далее :)



Есть другие варианты ... но они упераются в поставленую задачу.

Сообщение изменено: Incubo (16 мая 2008 - 21:49 )

  • 0
Victoria nulla est, Quam quae confessos animo quoque subjugat hostes ...
Верю в смерть после жизни, любовь после секса и в крем после бритья ...

#5 Fors

Fors
  • Пользователь
  • 328 сообщений

Отправлено 17 мая 2008 - 08:27

идея с флоат позишн очень понравилась :)
  • 0

#6 ParadoxL

ParadoxL
  • Постоялец
  • 5 023 сообщений
  • Откуда:Edinburg

Отправлено 18 мая 2008 - 10:54

Fors, да ... но тут есть свои ограничения ... можно только конечно число перестановок , которое варьируется взависимости от точности избраного типа данных decimal (float, double , big decimal) и от количества delta = (n, n-1),(n-1,n-2) , ... (k,k-1) , ... (n[1],n[0]) ... чем больше начальная дельта ... тем больше ... возможных перестановок в каждой дельте ... как вариант ... ввести некую критическую состовляющую ... при превышении которой идет полная переиндексация всех записей на основе текущей позиции каждого элемента.

Напрмер ... после определенного количества перестановок мы имеет.
Например, у нас есть
idx|	value|	pos
5		e		0.00001
3		c		0.00002
1		a		1.11564
4		d		3.12345
2		b		3.12346

Предел delta = 10^-5 ... то есть если будет проиходит еще перестановка в первых элементах, то будет борода. Из-за этого делаем проверку SQL ...
select min(position) as mPos from table

сравниваем mPos с нашим пределом ... если их разность бесконечно мала (в пределех 1 * 10^-5), то делаем перераздацу весов (переиндексирование). Напрмер с шагом в 10000 (в раельности на на децл порядком больше, но для простоты изложения обойдемся этим). Имеем ...

idx|	value|	pos
5		e		10000
3		c		20000
1		a		30000
4		d		40000
2		b		50000

И можено жить дальше.

Выйгрышь перед постоянной переиндексацией на лицо ... MIN в несравненно наименьшее число тактов (читать секунд) ... нежели полная переиндексация с обновлением в каждом перемещении.

NB! И еще первый possition не имеет право по определению быть 0 так как при перетаскивании на нулевую позиции ... значение предела этого индекса бесконечно стремиться к нулю.

ЗЫ! Надеюсь объяснил доходчиво...
  • 0
Victoria nulla est, Quam quae confessos animo quoque subjugat hostes ...
Верю в смерть после жизни, любовь после секса и в крем после бритья ...

#7 StrikeR

StrikeR

    бугога

  • Постоялец
  • 798 сообщений
  • Откуда:QLD. Australia

Отправлено 18 мая 2008 - 14:46

фух, пасиба, буду разбирться:) На самом деле, поле, как pos присудствовало, но я его приравнял к id в данном примере. Теперь буду сидеть и разбираться:) Ещё раз спасибо.
  • 0

#8 Equals

Equals
  • Пользователь
  • 76 сообщений

Отправлено 20 мая 2008 - 18:35

Зачем какой-то флоат позишн? зачем усложнять?
А поле по котому будет сортироваться, действительно надо добавить например 'position'.

mysql>
SET @old_position	= $old_position;	 --номер старой позиции
SET @new_position	= $new_position;  --номер новой позиции
SET @changed_element = $changed_id;  --объект
SET @change_element  = $change_id;   --объект на место которого встанет @changed_element

UPDATE table SET position = @new_position WHERE id=@change_element;
UPDATE table SET position = @old_position WHERE id=@changed_element;

Можно написать процедуру.
Перетаскива сколько душе угодно, без ограничений.
  • 0

#9 StrikeR

StrikeR

    бугога

  • Постоялец
  • 798 сообщений
  • Откуда:QLD. Australia

Отправлено 20 мая 2008 - 23:45

Equals, ты малёх недопонял в чём сосба вопрос был;) тут не нужно тупо менять местами два элемента...
  • 0

#10 Equals

Equals
  • Пользователь
  • 76 сообщений

Отправлено 21 мая 2008 - 10:55

StrikeR,

в общем-то твоя задача, не что иное, как тупая замена мест.
  • 0

#11 shb

shb

    New life, much more options

  • Постоялец
  • 5 253 сообщений
  • Откуда:Таллинн

Отправлено 21 мая 2008 - 11:03

Equals, посчитай, сколько операций придется делать базе, чтобы тупо переписать все индексы после каждой записи. Нормально?

Инкубо отличный вариант предложил :)
  • 0
Мыслящий человек просто обязан время от времени поднимать себя за волосы © Тот самый Мюнгхаузен

Joga Bonito!

#12 ParadoxL

ParadoxL
  • Постоялец
  • 5 023 сообщений
  • Откуда:Edinburg

Отправлено 21 мая 2008 - 17:03

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

Сообщение изменено: Incubo (21 мая 2008 - 17:04 )

  • 0
Victoria nulla est, Quam quae confessos animo quoque subjugat hostes ...
Верю в смерть после жизни, любовь после секса и в крем после бритья ...

#13 Equals

Equals
  • Пользователь
  • 76 сообщений

Отправлено 21 мая 2008 - 18:18

Убедили :X:D
  • 0