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

Вниз

Как лучше удалить из масива элементы?   Найти похожие ветки 

 
Vvedensk   (2004-01-26 19:52) [0]

Привет вот тут такая пробла..
Есть масив из 10 строк (масив динамический) мне надо удалить 5ю строку... как это сделать?
вот думал сделать вот так
typeL:= copy(typeL,0,int) + copy(typeL,int,length(typel));
где typeL масив
int номер строки которую надо удалить
:( не прокатило
попутно вопрос номер 2 как сложить 2 масива?

и вобще как лучше проводить эти операцие(в смысле скорости и экономии ресурсов)


 
Serginio666   (2004-01-26 20:01) [1]

move(typeL[int+1],typeL[int],(length(typel)-int-1)*SizeOf(тип Данных Массива));
SetLength(typeL,Length(typeL)-1);


 
Тимохов ©   (2004-01-26 20:03) [2]


> и вобще как лучше проводить эти операцие(в смысле скорости
> и экономии ресурсов)

Лучше вообще дин массивами не пользоваться если тебя интересует скорость. В некторых операциях они сильно проигрывают.

Если элементов всего 10 - то как проводить операции абсолютно не важно. Если элементов 100000, то лучше пользоваться TList или TStringList.


 
Тимохов ©   (2004-01-26 20:05) [3]


> move(typeL[int+1],typeL[int],(length(typel)-int-1)*SizeOf(тип
> Данных Массива));
> SetLength(typeL,Length(typeL)-1);

Ага... А finalize для элементов, которые удалены кто вызывать будет.
Если пользоваться move, то надо сначала typel[int] := "" (т.е. очистить строку). Иначе утечка будет, причем нефиговая.


 
Serginio666   (2004-01-26 20:15) [4]

Данный пример для одного элемента а для n

move(typeL[int+n],typeL[int],(length(typel)-int-n)*SizeOf(тип Данных Массива));
SetLength(typeL,Length(typeL)-n);

2 Тимохов © (26.01.04 20:05) [3]
Да Net накладывает отпечаток.


 
Тимохов ©   (2004-01-26 20:18) [5]


>
> 2 Тимохов © (26.01.04 20:05) [3]
> Да Net накладывает отпечаток.

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


 
Serginio666   (2004-01-26 20:24) [6]

Да нет. Просто в Net не нужно следить за уничтожением объекта.
Поэтому Free и Destroy для обычных объектов не применяется, Кроме тех которые не реализуют IDisposeble.
Это я о себе. Конечно ты прав.
Кстати 2 Vvedensk (26.01.04 19:52)
Посмотри реализацию TList и TStringList они небольшие, но все приемы там есть.


 
Тимохов ©   (2004-01-26 20:25) [7]

Serginio666 (26.01.04 20:24) [6]
Про отпечаток понял :)))

Кстати 2 Vvedensk (26.01.04 19:52)
Еще для развития пожешь посмотреть finalize и initialize


 
Serginio666   (2004-01-26 20:30) [8]

Кстати для динамических массивов память выделяется из Менеджера памяти в отличие от TList и TStringList. Поэтому при изменении капасити динамические массивы чувствуют себя лучше особенно при больших объемах данных. И последнее при полном заполнении лучше изменять каппасити сразу в 2 раза. Этим сразу можно убрать много проблем при перераспределении памяти и ее фрагментации.


 
Тимохов ©   (2004-01-27 09:33) [9]


> Кстати для динамических массивов память выделяется из Менеджера
> памяти в отличие от TList и TStringList

А для TList и TStringList откуда? Да от-туда же...
А капасити у Tlist и Tstringlist именно так и выделяется, в два раза...
По добавлению элементов как раз TList сильно выигрывает у дин массивов.


 
Serginio666   (2004-01-27 13:59) [10]

Ага
procedure TList.Grow;
var
Delta: Integer;
begin
if FCapacity > 64 then
Delta := FCapacity div 4
else
if FCapacity > 8 then
Delta := 16
else
Delta := 4;
SetCapacity(FCapacity + Delta);
end;
Где ты видишь в 2 раза. Только перекрыв данный метод.

А вот для TMemoryStream не используется Менеджер памяти и поэтому тормоза при больших объемах.
function TMemoryStream.Realloc(var NewCapacity: Longint): Pointer;
begin
if (NewCapacity > 0) and (NewCapacity <> FSize) then
NewCapacity := (NewCapacity + (MemoryDelta - 1)) and not (MemoryDelta - 1);
Result := Memory;
if NewCapacity <> FCapacity then
begin
if NewCapacity = 0 then
begin
{$IFDEF MSWINDOWS}
GlobalFreePtr(Memory);
{$ELSE}
FreeMem(Memory);
{$ENDIF}
Result := nil;
end else
begin
{$IFDEF MSWINDOWS}
if Capacity = 0 then
Result := GlobalAllocPtr(HeapAllocFlags, NewCapacity)
else
Result := GlobalReallocPtr(Memory, NewCapacity, HeapAllocFlags);
{$ELSE}
if Capacity = 0 then
GetMem(Result, NewCapacity)
else
ReallocMem(Result, NewCapacity);
{$ENDIF}
if Result = nil then raise EStreamError.CreateRes(@SMemoryStreamError);
end;
end;
end;

Для него лучше использовать массив блоков большого размера например http://www.1c.hippo.ru/cgi-bin/predownl.cgi?id=2019

А для больших динамических массивов лучше использовать типизированные двухуровневые массивы например

http://www.rsdn.ru/Forum/Message.aspx?mid=450320&only=1

Правда на дженериках, но под Delphi написать как два пальца.


 
Тимохов ©   (2004-01-27 14:13) [11]

1.

>>Где ты видишь в 2 раза. Только перекрыв данный метод.
Ну на одну четрверть, что не суть.
Я знал, что это так, просто для примера достаточно понимание, что в два раза.

2.

Какое отношение к дин. массивам имеет MemoryStream?


 
Serginio666   (2004-01-27 14:34) [12]

Суть большая, особенно при неправильном выбранном начальном каппасити.
А выделение памяти у них аналогичное но MemoryStream не использует МП и при больших объемах тормоза начинают сказываться раньше. А сделать свой типизированый динамический массив с использование каппасити не сложная задача и будет быстрее в 2 раза на доступ (но на вставку будет проигрывать).


 
Тимохов ©   (2004-01-27 14:45) [13]

Да при чем тут мемори стрим! Он ни к выделению памяти для TList ни для dynamic array отношения никакого не имеет. В случае динамических массивов и Tlist используется AllocMem. Т.е. используется менеджер памяти.

В случае если есть потребность добавлять элементы по одному, т.е. не известна заранее длина списка, то лучше пользоваться TList. Это примерно в 5 раз быстрее, чем для каждого нового элемента массива вызывать SetLength(Arr, Length(Arr)+1)

Если длина списка известна, то бустрее всего сразу выполнить SetLength(Arr, NumberOfItems). И потом устанавливать значения по одному. Это будет быстрее, чем TList (даже с заранее установленным колическом элементов) примерно в 2 раза. Причина в том, что TList класс и на каждую строку List[I] := SomeThing будет вызываться метод TList.Set. Что существенно медленне, чем Arr[I] := SomeThing (здесь будет прямая запись в память нового значения).

Сухой остаток. Выбор чем пользоваться зависит от задачи. В предыдущих двух абзацах сказано как лучше решать каждую задачу.

PS. Рассматривался случай хранения большого колическа значений типа Integer. Для строк, возможно, будет все иначе.


 
Serginio666   (2004-01-27 14:55) [14]

А ты читать умеешь имей count и
If Count=Length(Arr) Then
SetLength(Arr, Length(Arr)*2) в чем проблемы????
И уверяю тебя далеко оставит TList. Просто при распределении памяти и вставке при размере элемента массива больше 4 есть нюансы.


 
Тимохов ©   (2004-01-27 15:05) [15]

Так конечно быстрее всего.
Не спорю, и не спорил.
Только имхо это не очень удобно: нужно держать Count, нужно уметь делать Pack. И все такое. Одним словом, при активном использовании такого подхода, уверен, захочется это все запихнуть в класс. Т.о. получится тот же Tlist. Ровно с той же скоростью.

Вообще на эту тему я продолжаю говорить по той причине, что в ваших высказваниях была очевидная и пока не признанная вами ошибка:
"Кстати для динамических массивов память выделяется из Менеджера памяти в отличие от TList и TStringList"
На самом деле TList использует тот же самый менеджер памяти.


 
Serginio666   (2004-01-27 15:15) [16]

Согласен В этом ошибся спутав с MemoryStream, прошу прощения. К сожалению, сейчас нечасто беру в руки Delphi. Надеюсь исправить сей факт с появлением 8 ки.
По поводу неудобства и удовства, то 2 -3 лишних строчки кода не проблема, слишком примитивные алгоритмы, но и их не знают, а применяя данный подход можно хорошо набить руку.



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

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

Наверх




Память: 0.51 MB
Время: 0.023 c
3-16066
Grihan
2004-01-12 09:49
2004.02.06
Создание базы Interbase с определенной кодировкой


8-16535
vev
2003-10-07 09:59
2004.02.06
Работа с цифровой фотокамерой


1-16368
SniZ
2004-01-24 00:27
2004.02.06
Как создать маленькое приложение с формой?


6-16558
Alien
2003-12-02 07:10
2004.02.06
Как по IP узнать сетевое имя компа.... и наоборот


14-16654
konstantinov
2004-01-11 03:31
2004.02.06
Кто нибудь что нибудь знает о Норбекове