Форум: "Основная";
Текущий архив: 2004.09.26;
Скачать: [xml.tar.bz2];
ВнизЕсть ли функция для удаления 1 элемента из динамического масива? Найти похожие ветки
← →
bloodman © (2004-09-01 19:54) [0]Есть ли функция для удаления 1 элемента из динамического масиваб и последующим изменением его длины??
А то не хочется писать свою, наверняка же есть...
← →
Семен Сорокин © (2004-09-01 20:06) [1]есть для последнего SetLength(arr, Length(arr)-1), а еще есть Move.
PS.
Используй TList или его наследников.
← →
Romkin © (2004-09-01 20:51) [2]TList на самом деле только растет :))
http://www.delphimaster.ru/articles/dyntable/index.html
Легко адаптировать под массив ;)
← →
Fay © (2004-09-01 21:04) [3]2 bloodman © (01.09.04 19:54)
Твой вопрос длиннее той функции, которую не хочется писать.
← →
Endi (2004-09-01 22:07) [4]Я пользуюсь вот этой функцией.
procedure Delete(Idx:integer;M:array of integer); //Idx - индекс, с который нужно удалить
var
i:integer;
begin
for i:=Idx to Length(M)-2 do begin
M[i]:=M[i+1];
end;
SetLength(M,Length(M)-1);
end;
← →
Palladin © (2004-09-01 22:12) [5]
> Endi (01.09.04 22:07)
Почитай справку про Move, очень оптимизируешь свою функцию...
← →
bloodman © (2004-09-01 22:22) [6]Fay © (01.09.04 21:04) [3]
Да собственно я решил без функции обойтись:
For Z:=I to Length(DB) - 2 do DB[Z]:= DB[Z+1];
SetLength(DB, Length(DB) - 1);
:)
← →
Семен Сорокин © (2004-09-02 09:47) [7]
> Romkin © (01.09.04 20:51) [2]
> TList на самом деле только растет :))
> http://www.delphimaster.ru/articles/dyntable/index.html
> Легко адаптировать под массив ;)
Отличная статья.
← →
Erik1 (2004-09-02 12:00) [8]To bloodman
Ну ты даеш.
i := удаляемый элемет масива
Size := Length(DB);
Move(DB[i + 1], DB[i], (Size - i) * SizeOf(DB[0]));
Setlength(DB, Size-1);
И все.
← →
bloodman © (2004-09-05 13:39) [9]НЕТ не все. Этот код у меня не правильно работает! Вот функция:
function Create(DB : TDBDinArray):boolean;
begin
...
Move(DB[I + 1], DB[I], ( Length(DB) - I) * SizeOf(DB[0]));
Setlength(DB, Length(DB) -1);
...
end;
вызываю так:
res:=Create(RightDB);
А происходит вот что : При первом вызове этой функции(move) она удалает первый элемент не только в DB (лок переменная) но и в RightDB !! почему ??? Мне этого не нужно..
← →
bloodman © (2004-09-05 13:49) [10]блин бред какой то
For Z:=I to Length(DB) - 2 do DB[Z]:= DB[Z+1];
тоже удаляет первый элемент . Ж((
наверно даже не удаляет а сдвигает адрес первого элемента на размер записи :( ПОЧЕМУ ??? не понимаю там ведь даже удаления то нету...
← →
bloodman © (2004-09-05 14:27) [11]Что никто не знает ответа????
Почему удаляется у RigthDB первый элемент?? Остальные то остаются... ???
type
TDBDinArray = array of TDBRecord;
← →
begin...end © (2004-09-05 14:33) [12]
> [11] bloodman © (05.09.04 14:27)
Что за RightDB? Где код?
← →
bloodman © (2004-09-05 14:37) [13]RightDB : TDBDinArray;
function Create(DB : TDBDinArray):boolean;
begin
...
Move(DB[I + 1], DB[I], ( Length(DB) - I) * SizeOf(DB[0]));
Setlength(DB, Length(DB) -1);
...
end;
вызываю так:
res:=Create(RightDB);
type
TDBRecord = record
ID : Integer;
Father : Integer;
Name : String[30];
Path : String[255];
Parameters : string[30];
Shortcut : string[30];
IconPath : String[255];
end;
type
TDBDinArray = array of TDBRecord;
Собственно херня ета происходит на move (или на for без разници) причем при первом вызове , то есть когда удаляется нулевой елемент потом все нормально идет- из rightdb ничего не удаляется.
← →
bloodman © (2004-09-05 14:46) [14]Сделал так чтобы процесс пошел не с нулевого елемента , все равно просто удалился первый :((
← →
bloodman © (2004-09-05 21:49) [15]что никто не знает???
← →
Defunct © (2004-09-05 23:37) [16]Там где часто приходится удалять. Лучше использовать динамический односвязный список, а не массив.
тогда удаление сводится к двум действиям:
- освобождение памяти
- выброс элемента из цепочки.
Возвращаясь к вашему вопросу. Удаление элемента из динамического массива - действие трудоемкое, но осуществимое.Procedure Delete(var DynArray: TYoursDynamicArray; ItemIndex: Integer);
Var I:Integer;
Begin
If ItemIndex< Length(DynArray) Then
Begin
For I:=ItemIndex+1 To Length(DynArray)-1 Do DynArray[i-1] := DynArray[i];
SetLength(DynArray, Length(DynArray)-1);
End;
End;
← →
bloodman © (2004-09-05 23:47) [17]Defunct © (05.09.04 23:37) [16]
Ваща процедура аналогична моей , даже больше , это одно и тоже .
Для чего это нужно было приводить не понятно. Вопрос был не в том КАК это сделать, а в том что почему-то удаляется элемент из основного масива, хотя не должен...
Односвязный список - это TList??
← →
Defunct © (2004-09-06 00:11) [18]> Для чего это нужно было приводить не понятно. Вопрос был не в том КАК это сделать, а в том что почему-то удаляется элемент из основного масива, хотя не должен...
Сюдя из Ваших постингов это понять нельзя, более того, вообще непонятно какое отношение имеет название функции "Create" - создать к первоначальному вопросу "Как удалить" т.е. "Delete".> Procedure Delete(var DynArray: TYoursDynamicArray; ItemIndex: Integer);
Идем далее, выделенный var в заголовке приведенной мной процедуры задает область действия процедуры на основной массив, т.е. тот массив (DynArray), который будет передаваться в процедуру как параметр. Если не требуется удалять элемент массива, тогда вы можете убрать оттуда var, и элемент из основного массива удаляться не будет.
Ну и раз уж у вас получается непонятно что. То будьте добры не ходите вокруг да около с возгласами:
> Собственно херня ета происходит на move (или на for без разници) причем при первом вызове
А сформулируйте вопрос нормально. Что именно вы хотите сделать?
> Односвязный список - это TList??
Односвязный список - это односвязный список. Например, такой:
PDataRec = ^TDataRec;
TDataRec = Record
MyData : TMyData;
Next: PDataRec;
End;
У вас должны быть 2 указателя, на голову списка (1-й элемент) и, необязательно, на хвост списка (последний элемент). Промежуточные элементы всталяются в цепочку с помощью указателя Next
Работать с таким списком так:
P := Head;
While P<>Nil Do P := P.Next;
Выбрасывать (удалять) элемент:
P2 := P.Next;
P.Next := P2.Next;
Dispose(P2);
А TList - это TList, и неизвестно, что в него Borland вставил, является он односвязным списком или нет, нужно смотреть по коду.
← →
Erik1 (2004-09-06 10:04) [19]Интересная у тебя функция Create(DB : TDBDinArray):boolean, вот бы еще узнать, что у тебя в I присваевается. :)
К томуже ненадо выкидавать переменую Size.
← →
Romkin © (2004-09-06 11:58) [20]Defunct © (06.09.04 00:11) [18] ТАк код TList посмотреть можно. И даже рекомендуется :)
Там фактически динамический массив, но только растет, не уменьшается. И, кстати, сделано весьма грамотно: это не dynamic array, а указатель на тип массив. Память же выделяется блоками, с запасом.
Вообще говоря, тип данных для хранения структуры выбирать надо строго исходя из тех действий, которые будут делаться. А абстрактных типов данных довольно много, выбор есть. Навскидку: массив, список (однонаправленный, двунаправленный, многосвязный), куча (двоичная, биномиальная...), двоичное дерево и тд :))
← →
Erik1 (2004-09-06 13:35) [21]To Romkin
Я думаю, что вот это "куча (двоичная, биномиальная...), двоичное дерево" автор за ругательство примет :)
← →
bloodman © (2004-09-06 22:44) [22]Defunct © (06.09.04 00:11) [18]
>>Ну и раз уж у вас получается непонятно что. То будьте добры не >>ходите вокруг да около с возгласами:
>>> Собственно херня ета происходит на move (или на for без >>разници) причем при первом вызове
>>А сформулируйте вопрос нормально. Что именно вы хотите сделать?
ок . Мне требуется передать в функцию динамический масив. В ней я постепенно удаляю все его элементы.Но мне нужно что бы этот масив остался в сохранности вне функции т.е. в ней нужно работать с его конией поэтому у меня в функции параметра VAR перед масивом нет. НО все равно из него удаляется элемент при первом вызове процедуры move - это и есть моя проблема.
← →
Defunct © (2004-09-06 23:13) [23]> Мне требуется передать в функцию динамический масив. В ней я постепенно удаляю все его элементы.Но мне нужно что бы этот масив остался в сохранности вне функции т.е. в ней нужно работать с его конией поэтому у меня в функции параметра VAR перед масивом нет.
Стоп. Здесь противоречие, зачем удалять элементы так, чтобы ничего не удалялось? Где логика? Сформулируйте пожалуйста цель вашего, как бы это лучше выразиться, шаманства.
> НО все равно из него удаляется элемент при первом вызове процедуры move - это и есть моя проблема.
Ответ на вопрос "почему удаляются элементы вне функции?" прост - динамический массив предствляет собой указатель на массив. Создайте копию массива внутри функции вручную, и работайте с ней.
Вопрос, зачем все это надо???
← →
bloodman © (2004-09-07 20:23) [24]>Создайте копию массива внутри функции вручную, и работайте с ней.
Это мне и нужно. Как лучше создать его копию.Я просто копирую элемент за элементом но ведь это медленно очень, пробовал с Copymem не получилось.
>Вопрос, зачем все это надо???
В процедуре я обрабатываю масив, чтобы не запоминать с какими жлементами я работал уже я их удаляю. Но потом вне этой функции я снова должен использовать этот масив. Вот поэтому мне нужна его копия внутри процедуры.
← →
Defunct © (2004-09-07 20:40) [25]> В процедуре я обрабатываю масив, чтобы не запоминать с какими жлементами я работал уже я их удаляю. Но потом вне этой функции я снова должен использовать этот масив. Вот поэтому мне нужна его копия внутри процедуры.
Вот с этого надо было и начинать, т.е. ваша цель выполнить какие-то действия над данными однократно. Решается это добавлением дополнительного поля в структуру данных с именем скажем: FServed:Boolean или FNeedProcessing:Boolean. Перед работой со всем массивом установите в каждой записи FNeedProcessing в True, а после выполнения действия сбрасывайте этот флажек.Procedure PrepareToDoSomething( DynArray: TYourDinamicArray);
var I:Integer;
Begin
For I:=0 To Length(DynArray)-1 Do DynArray[i].FNeedProcessing := True;
End;
Procedure DoSomething( DynArray: TYourDynamicArray);
Var I:Integer;
Begin
For I:=0 To Legnth( DynArray)-1 Do
If DynArray[i].FNeedProcessing Then
Begin
DynArray[i].FNeedProcessing := False;
..
<тут ваши действия над данными>
End;
End;
> Как лучше создать его копию.Я просто копирую элемент за элементом но ведь это медленно очень, пробовал с Copymem не получилось.
Да вы правы, это очень медленно. Особенно если много данных, то никто никогда не делает полное копирование.
← →
Defunct © (2004-09-07 21:06) [26]Конструктивный совет по улучшению вашей программы:
Откажитесь от Record, создайте класс TDataCell, в котором разместите все поля, добавьте в этот класс методы для работы с полями, сохранение/восстановление/удаление и прочее. Создайте наследника, TDataControl в котором, например, будет множество полей, и перекройте базовые методы, методами работы с множеством.
Например:Type
TSmallString = String[255];
TDataCell = class
Private
FID : Integer;
FFather : Integer;
FName : TSmallString;
FPath : TSmallString;
FParameters : TSmallString;
FShortcut : TSmallString;
FIconPath : TSmallString;
FEnabled : Boolean;
FDeleted : Boolean;
FServed : Boolean;
FChanged : Boolean;
Procedure SetName(AName: TSmallString);
Procedure SetPath(APath: TSmallString);
Procedure SetParams( AParams: TSmallString);
Procedure SetShortcut( AShortcut: TSmallString);
Procedure SetIconPath(APath: TSmallString);
Public
Property Enabled:Boolean Read Enabled;
Property Deleted:Boolean Read Deleted
Property Name:TSmallString Read FName Write SetName;
Property Path:TSmallString Read FPath Write SetPath;
Property Params:TSmallString Read FParams Write SetParams;
Property Shortcut:TSmallString Read FShortcut Write SetShortcut;
Property IconPath: TSmallString Read FIconPath Write SetIconPath;
Procedure PrepareToDoSomthing; Virtual;
Procedure DoSomething; Virtual;
....
и т.д. все что вам требуется выполнять над полями.
....
Procedure Save(Stream: TMemoryStream); Virtual;
Procedure Load(Stream: TMemoryStream); Virtual;
Constructor Create; Virtual;
Destructor Destroy; Virtual;
end;
TDataControl = class(TDataCell)
Private
FCount : Integer;
DataCells : Array of TDataCell
Procedure SetCell( Index:Integer; ACell: TDataCell);
Function GetCell( Index:Integer):TDataCell;
Public
Property Count: Integer Read FCount;
Property Items[Index: Integer]:TDataCell Read GetCell Write SetCell;
Procedure Add:TDataCell; Virtual;
Procedure PrepareToDoSomthing; Override;
Procedure DoSomething; Override;
....
и т.д. все что вам требуется выполнять над полями.
....
Procedure Save(Stream: TMemoryStream); Override;
Procedure Load(Stream: TMemoryStream); Override;
Constructor Create; Override;
Destructor Destroy; Override;
End;
Опишете так, зато потом будет проще работать. Например все сведется к:
Var DB : TDataControl;
Begin
DB := TDataControl.Create;
DB.Load( Stream );
DB.PrepareToDoSomething;
DB.DoSomething;
DB.Save( Stream );
DB.Free;
End;
← →
bloodman © (2004-09-08 00:01) [27]Спасибо за совет! Попробую сделать так.
Страницы: 1 вся ветка
Форум: "Основная";
Текущий архив: 2004.09.26;
Скачать: [xml.tar.bz2];
Память: 0.54 MB
Время: 0.037 c