Top.Mail.Ru
Мастера DELPHI, Delphi programming community Титульная страница Поиск, карта сайта Написать письмо 
| Новости | Поиск | FAQ | Статьи | Книги | Новости VCL |
| Форумы ЧАТ | Орешник | KOL и MCK |
Форумы -» Основная («Начинающим»)/ Базы / WinAPI / Компоненты / Сети / Media / Игры / Corba и COM / KOL / FreePascal / .Net / Прочее / RSDN.ORG

« предыдущая ветвь | форум | следующая ветвь »

У можно как-то у TList'a сделать эффектное массовое удаление? [D7, WinXP]


Страницы:   1 2

Aleksandr. ©   (2004-08-11 17:43:00) 

Тут у меня потомок 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;


TUser   (2004-08-11 20:07:00) [1]

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


Mim1   (2004-08-11 19:43:00) [2]

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


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

Mim1 ©  :

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


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

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


Mim1   (2004-08-11 19:05:00) [5]


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


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


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

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


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

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


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

Мастер ©  :

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


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

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:34:00) [10]

Мастер ©  :

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


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

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

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


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

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

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

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

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


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

> Мастер © :

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


Mim1   (2004-08-11 18:22:00) [14]


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


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


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

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

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


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

> Мастер ©  :

Выглядит красиво, но получается нестыковка:
Если у меня 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:12:00) [17]

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

Какое?


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


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

Да


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

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

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


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


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

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


Страницы:   1 2

Наверх

Титульная страница Поиск, карта сайта Написать письмо