Форум: "Основная";
Текущий архив: 2004.02.06;
Скачать: [xml.tar.bz2];
ВнизКак лучше удалить из масива элементы? Найти похожие ветки
← →
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;
Скачать: [xml.tar.bz2];
Память: 0.49 MB
Время: 0.03 c