Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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
1-16238
Alexey_
2004-01-20 16:34
2004.02.06
Свой .mpq файл


1-16345
Vitalik
2004-01-24 15:06
2004.02.06
Классы


1-16361
lkl
2004-01-24 12:37
2004.02.06
Помогите с фильтрацией в Edit???


14-16656
Magician
2004-01-17 16:41
2004.02.06
Как закачать файл с интернета используя несколько потоков.


14-16668
syte_ser78
2004-01-17 15:01
2004.02.06
Freepascal





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
Английский Французский Немецкий Итальянский Португальский Русский Испанский