Главная страница
    Top.Mail.Ru    Яндекс.Метрика
Форум: "Основная";
Текущий архив: 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.044 c
1-1094718598
V l a d i m i r
2004-09-09 12:29
2004.09.26
Если запущен Word, как активировать только что созданный документ


1-1094814970
redlord
2004-09-10 15:16
2004.09.26
как убить все объекты одним ударом


3-1093341693
ydv
2004-08-24 14:01
2004.09.26
запрос с помощью TADOCommand


1-1094808009
jonik
2004-09-10 13:20
2004.09.26
Создание построителя отчета


14-1094785169
YurikGL
2004-09-10 06:59
2004.09.26
Exchange 2000 и русские логины





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