Главная страница
Top.Mail.Ru    Яндекс.Метрика
Текущий архив: 2004.08.29;
Скачать: CL | DM;

Вниз

У можно как-то у TList a сделать эффектное массовое удаление?   Найти похожие ветки 

 
Aleksandr.   (2004-08-11 17:43) [0]

Тут у меня потомок TList работает, так вот при наборе в 500000 элементов удаляет он их достаточно медленно, если вызывать List.Delete(0). Смотрел я долго на всякие мувы, которые у него внутри происходят, но чего-то так ничего и не выцепил, как можно было бы одним обращением задать ему на удаление элементов так с тысячу:

procedure TList.Delete(Index: Integer);
var
 Temp: Pointer;
begin
 if (Index < 0) or (Index >= FCount) then
   Error(@SListIndexError, Index);
 Temp := Items[Index];
 Dec(FCount);
 if Index < FCount then
   System.Move(FList^[Index + 1], FList^[Index],
     (FCount - Index) * SizeOf(Pointer));
 if Temp <> nil then
   Notify(Temp, lnDeleted);
end;


 
Sandman25 ©   (2004-08-11 17:46) [1]

Похоже, что выбрана неверная структура данных. Поподробнее о задаче можно?


 
MacroDenS ©   (2004-08-11 17:47) [2]

удаление процесс обратный добавлению!
Добавляешь построчно - удаляешь построчно...


 
Ega23 ©   (2004-08-11 17:52) [3]

Можно только посоветовать свой список создать.
Например: каждый элемент хранить в структуре "указатель на объект" + "указатель на следующий элемент".
При удалении k-го элемента "указатель на следующий элемент" в (k-1)-м элементе перенаправлять на (k+1)-й элемент.

Правда тогда поледний элемент будет долго удалять :о)


 
Aleksandr.   (2004-08-11 17:53) [4]

Задача - превратить цикл
System.Move(FList^[Index + 1], FList^[Index],
    (FCount - Index) * SizeOf(Pointer));
в какое-то одно действие. Причем тут структура - освобождение тех же пятисот тысяч итемов перед удалением делается моментально. А вот на удалении тормоза.


 
Sandman25 ©   (2004-08-11 17:55) [5]

[4] Aleksandr.   (11.08.04 17:53)

После такого:
Причем тут структура
остается только спросить: "List.Clear не подойдет?"


 
Sandman25 ©   (2004-08-11 17:58) [6]

Напишите своего наследника TList, добавьте метод DeleteItems(FirstIndex, Count)


 
Aleksandr.   (2004-08-11 17:58) [7]

Нет, потому что удаляются не все элементы.


 
Aleksandr.   (2004-08-11 17:59) [8]

Ну, метод я добавил, но как его реализовать? Как массовый сдвиг сделать?


 
Мастер ©   (2004-08-11 18:04) [9]

Что-то такое примерно:
procedure TList.DeleteItems(Index1,Index2: Integer);
//var
//  Temp: Pointer;
begin
 if (Index1>Index2) or (Index1 < 0) or (Index2 >= FCount) then
   Error(@SListIndexError, Index);
//  Temp := Items[Index];
 Dec(FCount,Index2-Index1+1);
 if Index2 < FCount then
   System.Move(FList^[Index1 + 1], FList^[Index1],
     (FCount - Index2) * SizeOf(Pointer));
//  if Temp <> nil then
//    Notify(Temp, lnDeleted);
end;


Если необходимо, то можно переопределить TList.Notify


 
VMcL ©   (2004-08-11 18:06) [10]

>>Aleksandr.  (11.08.04 17:43)

Удалять в порядке Count - 1 downto 0 пробовал?


 
Mim1 ©   (2004-08-11 18:09) [11]


> [8] Aleksandr.   (11.08.04 17:59)

Вы не имеете досиупа в наследнике в переменной предка FList поскольку она private. Так что прийдется написать свой TAlxList (путем вынесения едшые из модуля classes и добавления нужного метода), или прийдется пойти методом > [3] хотя с оброением к элементу по индексу будет проблемма.


 
Мастер ©   (2004-08-11 18:09) [12]

>VMcL ©   (11.08.04 18:06) [10]
Удалять в порядке Count - 1 downto 0 пробовал?

А разве в данном случае это имеет значение?


 
Mim1 ©   (2004-08-11 18:12) [13]


> [12] Мастер ©   (11.08.04 18:09)

Да


 
Мастер ©   (2004-08-11 18:12) [14]

>Mim1 ©   (11.08.04 18:12) [13]
Да

Какое?


 
Aleksandr.   (2004-08-11 18:17) [15]

> Мастер ©  :

Выглядит красиво, но получается нестыковка:
Если у меня 500000 элементов, мне надо удалить с нулевого по 30000-й, то Index2 заведомо будет больше Count.

procedure TList.DeleteItems(Index1,Index2: Integer);
begin
if (Index1>Index2) or (Index1 < 0) or (Index2 >= FCount) then
  Error(@SListIndexError, Index);
Dec(FCount,Index2-Index1+1);
if Index2 < FCount then
  System.Move(FList^[Index1 + 1], FList^[Index1],
    (FCount - Index2) * SizeOf(Pointer));
end;


 
Мастер ©   (2004-08-11 18:20) [16]

>Aleksandr.   (11.08.04 18:17) [15]
Выглядит красиво, но получается нестыковка:

Что за нестыковка?


 
Mim1 ©   (2004-08-11 18:22) [17]


> [14] Мастер ©   (11.08.04 18:12)


После удаления на место удаленного элемента копируются все элементы стоящие после удаляемого. В случае downto копируется меньшее количество. Количество удаляемых элементов влияет на скорость.


 
Aleksandr.   (2004-08-11 18:26) [18]

> Мастер © :

Посмотрите на условие. Move для данного случая выполняться не будет, потому что:
 FCount=500000-300000+1 = 200001
 300000>200000, а по условию
 if Index2 < FCount then
 все наоборот.


 
Мастер ©   (2004-08-11 18:29) [19]

>Aleksandr.   (11.08.04 18:26) [18]

Ну так подправь-)

>Mim1 ©   (11.08.04 18:22) [17]

СОгласен... В случае больших объемов будет заметно.


 
VMcL ©   (2004-08-11 18:32) [20]

>>Mim1 ©  (11.08.04 18:09) [11]

AFAIR, TList.List никто не отменял.


 
Aleksandr.   (2004-08-11 18:34) [21]

Мастер ©  :

Не получается подправить :(. Не мувится ничего.


 
Мастер ©   (2004-08-11 18:36) [22]

Aleksandr.   (11.08.04 18:34) [21]

procedure TList.DeleteItems(Index1,Index2: Integer);
begin
 if (Index1>Index2) or (Index1 < 0) or (Index2 >= FCount) then
   Error(@SListIndexError, Index);
 if Index2 < FCount then
   System.Move(FList^[Index1 + 1], FList^[Index1],
     (FCount - Index2-1) * SizeOf(Pointer));
 Dec(FCount,Index2-Index1+1)
end;
;


А так?


 
Aleksandr.   (2004-08-11 18:41) [23]

Мастер ©  :

Так так я и сделал:
 if ToIndex<FCount then
   System.Move(FList^[FromIndex+1], FList^[FromIndex],
              (FCount-ToIndex-1) * SizeOf(Pointer));
 Dec(FCount,ToIndex-FromIndex+1)
Бесполезно. Элементы с FromIndex по ToIndex остаются на своих местах.


 
Aleksandr.   (2004-08-11 18:47) [24]

В смысле, на один сдвиг между нулевым и первым происходит, а остальные на местах остаются.


 
Aleksandr.   (2004-08-11 18:59) [25]

Ой млин... а там сурсом у Move не FList^[ToIndex], часом, надо?


 
Mim1 ©   (2004-08-11 19:05) [26]


> [20] VMcL ©   (11.08.04 18:32)


Действительно :), каюсь моя ошибка. Тогда решение проблеммы мне видется очень простым.


 
Aleksandr.   (2004-08-11 19:05) [27]

Ха-ха! Ну и бандарлог же я! Конечно, стартовый для смещения надо было задавать следующий от конечного индекса! Работает одним легким движением! Всем спасибо.


 
Aleksandr.   (2004-08-11 19:10) [28]

Mim1 ©  :

А какое Вам видится решение?


 
Mim1 ©   (2004-08-11 19:43) [29]

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


 
TUser ©   (2004-08-11 20:07) [30]

TList использует массивы, а тебе нужны связные списки. Они для удаления/добавления лучше (в смысле быстреее).



Страницы: 1 вся ветка

Текущий архив: 2004.08.29;
Скачать: CL | DM;

Наверх




Память: 0.53 MB
Время: 0.041 c
6-1088472500
hyper_omsk
2004-06-29 05:28
2004.08.29
(ping) Отсутствует сетевое подключение


4-1090223134
DmitryMN
2004-07-19 11:45
2004.08.29
Поиск директории Program Files


1-1092401649
Nata
2004-08-13 16:54
2004.08.29
Файлы


6-1088582076
Nic2
2004-06-30 11:54
2004.08.29
ClientSocket и тайм-аут


14-1092299325
Странник
2004-08-12 12:28
2004.08.29
Туркменбаши приказал построить рядом с Ашхабадом дворец из льда