Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 2004.08.29;
Скачать: [xml.tar.bz2];

Вниз

У можно как-то у 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;
Скачать: [xml.tar.bz2];

Наверх





Память: 0.52 MB
Время: 0.042 c
1-1092308148
Zlodey
2004-08-12 14:55
2004.08.29
qtintf70.dll


1-1092395892
NikeOLD
2004-08-13 15:18
2004.08.29
Отловить изменение ширины колонки ListView


1-1092417058
Gnec
2004-08-13 21:10
2004.08.29
Как сделать перескок к нужному итему?


14-1092373646
menart
2004-08-13 09:07
2004.08.29
Код, и как его надо писать?


14-1092309198
ilya__
2004-08-12 15:13
2004.08.29
Мне предложили опубликовать мою программу





Afrikaans Albanian Arabic Armenian Azerbaijani Basque Belarusian Bulgarian Catalan Chinese (Simplified) Chinese (Traditional) Croatian Czech Danish Dutch English Estonian Filipino Finnish French
Galician Georgian German Greek Haitian Creole Hebrew Hindi Hungarian Icelandic Indonesian Irish Italian Japanese Korean Latvian Lithuanian Macedonian Malay Maltese Norwegian
Persian Polish Portuguese Romanian Russian Serbian Slovak Slovenian Spanish Swahili Swedish Thai Turkish Ukrainian Urdu Vietnamese Welsh Yiddish Bengali Bosnian
Cebuano Esperanto Gujarati Hausa Hmong Igbo Javanese Kannada Khmer Lao Latin Maori Marathi Mongolian Nepali Punjabi Somali Tamil Telugu Yoruba
Zulu
Английский Французский Немецкий Итальянский Португальский Русский Испанский