Link to home
Start Free TrialLog in
Avatar of wildzero
wildzero

asked on

Remove item from dynamic array

Hmm ok must be having a slow day!

How can I remove an item from a dynamic array?
If I have an array of 50 items, and I want to remove 3-4 from around the midddle / end of the array - how can I go about doing that?
Can I set some to null / nil and then setlength again?

Avatar of xr1140
xr1140

i'm using this :


procedure delArrayItem(Index: Integer);
begin

  if Index > High(aArray) then Exit;
  if Index < Low(aArray) then Exit;

  if Index = High(aArray) then begin
    SetLength(aArray, Length(aArray) - 1);
    Exit;
  end;

  Finalize( aArray[Index] );
  System.Move( aArray[Index +1], aArray[Index], (Length(aArray) - Index - 1) * SizeOf(string) + 1);
  SetLength(aMenus, Length(aArray) - 1);
end;
Avatar of dinilud
Try this

Unit1.dfm
========

object Form1: TForm1
  Left = 157
  Top = 159
  Width = 472
  Height = 354
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'MS Sans Serif'
  Font.Style = []
  OldCreateOrder = False
  OnCreate = FormCreate
  PixelsPerInch = 96
  TextHeight = 13
  object Memo1: TMemo
    Left = 32
    Top = 16
    Width = 193
    Height = 249
    Lines.Strings = (
      'Memo1')
    TabOrder = 0
  end
  object Button1: TButton
    Left = 248
    Top = 96
    Width = 145
    Height = 33
    Caption = 'Del 3,4,5'
    TabOrder = 1
    OnClick = Button1Click
  end
end

Unit1.pas
=======

unit Unit1;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  MyArrayType = Double;

  TForm1 = class(TForm)
    Memo1: TMemo;
    Button1: TButton;
    procedure FormCreate(Sender: TObject);
    procedure Button1Click(Sender: TObject);
  private
    { Private declarations }
    x:array of MyArrayType;
    procedure DisplayArray;
  public
    { Public declarations }
  end;

var
  Form1: TForm1;

implementation

{$R *.dfm}

function DeleteArray(var Source:array of MyArrayType;LenSource:Integer;
                          Del_IndexList:array of Integer; DelCount:Integer):Integer;
   Function IsInDel_IndexList(idx:Integer):Boolean;
     var i:Integer;
   begin
     Result:=False;
     for i:=0 to DelCount do
     begin
       if Del_IndexList[i]=idx then
       begin
          Result:=True;
          Break;
       end;
     end;
   end;
  var CurIdx,DCount:Integer;
begin
  CurIdx:=0;
  DCount:=0;
  While CurIdx<LenSource do
  begin
     if IsInDel_IndexList(CurIdx) then Inc(DCount);
     if CurIdx-DCount>-1 then
       Source[CurIdx-DCount]:=Source[CurIdx];
     inc(CurIdx);
  end;
  Result:=DelCount;
end;

procedure TForm1.DisplayArray;
var i:Integer;
begin
  Memo1.Clear;
  for i:=0 to length(x)-1 do Memo1.Lines.Add(FloatToStr(x[i]));
end;

procedure TForm1.FormCreate(Sender: TObject);
var i:Integer;
begin
  SetLength(x,10);
  for i:=0 to 9 do x[i]:=i+1;
  DisplayArray;
end;

procedure TForm1.Button1Click(Sender: TObject);
begin
  SetLength(X,length(X)-DeleteArray(X,length(X),[3,4,5],3));
  DisplayArray;
end;

end.
best solution would be using one call to copy memory.
This is the 'problem' of dynamic arrays... actions like these are soooo sloooowww...

I'll post an example using copymemory later.
SOLUTION
Avatar of Pierre Cornelius
Pierre Cornelius
Flag of South Africa image

Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Avatar of wildzero

ASKER

Hmmm true, I was going to but then I would have to write the code for adding / finding the index of an deleting records from the list wouldn't I?

I am using the suggestion that xr1140 has posted (actually, I was using the code from about.com which happens to look like his :P)

Interested in this TList approach.
Upping points
this one seems to work


var
  myList : TList;

procedure delArrayItem(Index: Integer);
var obj : TmyObjType;
begin

  if Index < 0 then Exit;
  if Index > myList.Count then Exit;

  obj := myList.Items[Index];

  myList.Delete(Index);

  FreeAndNil(obj);

end;
Is a record classed as an object?
How would I got about adding/editing a record on a list?

(points upped)
same thing from the above link




uMain.dfm
===================


object Form1: TForm1
  Left = 449
  Top = 295
  Width = 484
  Height = 231
  Caption = 'Form1'
  Color = clBtnFace
  Font.Charset = DEFAULT_CHARSET
  Font.Color = clWindowText
  Font.Height = -11
  Font.Name = 'Tahoma'
  Font.Style = []
  OldCreateOrder = False
  PixelsPerInch = 96
  TextHeight = 13
  object butAdd: TButton
    Left = 5
    Top = 10
    Width = 176
    Height = 21
    Caption = 'Add item to list'
    TabOrder = 0
    OnClick = butAddClick
  end
  object Memo1: TMemo
    Left = 185
    Top = 5
    Width = 281
    Height = 191
    TabOrder = 1
  end
  object butDisplay: TButton
    Left = 5
    Top = 170
    Width = 176
    Height = 26
    Caption = 'Display list content'
    TabOrder = 2
    OnClick = butDisplayClick
  end
  object butRemove: TButton
    Left = 5
    Top = 55
    Width = 101
    Height = 21
    Caption = 'Remove index'
    TabOrder = 3
    OnClick = butRemoveClick
  end
  object Edit1: TEdit
    Left = 110
    Top = 55
    Width = 71
    Height = 21
    TabOrder = 4
    Text = '0'
  end
end




uMain.pas
===================


unit uMain;

interface

uses
  Windows, Messages, SysUtils, Variants, Classes, Graphics, Controls, Forms,
  Dialogs, StdCtrls;

type
  TmyObjType = class
    Name : String;
    constructor Create(S: string);
  end;


  TForm1 = class(TForm)
    butAdd: TButton;
    Memo1: TMemo;
    butDisplay: TButton;
    butRemove: TButton;
    Edit1: TEdit;
    procedure butAddClick(Sender: TObject);
    procedure butDisplayClick(Sender: TObject);
    procedure butRemoveClick(Sender: TObject);
  private
    { Private declarations }
  public
    { Public declarations }
  end;

var
  Form1: TForm1;
  myList : TList;

implementation

{$R *.dfm}

constructor TmyObjType.Create(S: string);
begin
  Name := S;
end;

procedure delArrayItem(Index: Integer);
var
  obj : TmyObjType;
begin

  if Index > myList.Count then Exit;
  if Index < 0 then Exit;

  obj := myList.Items[Index];

  myList.Delete(Index);
  FreeAndNil(obj);

end;


procedure TForm1.butAddClick(Sender: TObject);
var
  obj : TmyObjType;
begin
  if myList = nil then begin
    myList := TList.Create;

  end;

  obj := TmyObjType.Create( 'Item with index - ' + IntToStr(myList.Count) );
  myList.Add(obj);

end;

procedure TForm1.butDisplayClick(Sender: TObject);
var i: integer;
begin
  memo1.Clear;

  for i := 0 to (myList.Count-1) do begin
    memo1.Lines.Add( TmyObjType(myList.Items[i]).Name );
  end;

end;

procedure TForm1.butRemoveClick(Sender: TObject);
begin
  delArrayItem( StrToInt(Edit1.Text) );
end;

end.
Nuice, thanks :-)
type
  TmyObjType = class
    Name : String;
    constructor Create(S: string);
  end;
--------------------------------------------
will this work with records?

ASKER CERTIFIED SOLUTION
Link to home
membership
This solution is only available to members.
To access this solution, you must be a member of Experts Exchange.
Start Free Trial
Well done, top effort!

thank you, i'm glad i could be of help