例如:
type
TMyArr = array of string;
var
aMyArr: TMyArr;
begin
SetLength(aMyArr, 10000);
//如果我想删除第5000个元素,如何快速的删除它?
end;如果是一个链表,那么可以把第4999个元素的指针指向第5001个元素,同理第5001个元素的指针指向第4999个元素,就完成了这个删除的操作。但是在Delphi里类似这样的动作如何处理呢?
type
TMyArr = array of string;
var
aMyArr: TMyArr;
begin
SetLength(aMyArr, 10000);
//如果我想删除第5000个元素,如何快速的删除它?
end;如果是一个链表,那么可以把第4999个元素的指针指向第5001个元素,同理第5001个元素的指针指向第4999个元素,就完成了这个删除的操作。但是在Delphi里类似这样的动作如何处理呢?
要么就用2维数组,把另一维用0和1纪录着数据是否被删除?
要么用zhengji(看雨飞) 的方法:写个链表类,但给出按序号取元素的方法,以此来模拟数组?其他朋友还有其他的做法吗?
它有delete方法
添加数据用add方法如果非要数组的话,也没什么好的方法
引用ctcpp的看法:那就移动它后面的元素向前一个位置吧,或者新建一个一样大的数组,把旧的除了[500]之外的依次拷进去,好像C++中String类就是这样实现的
==========================================================================================
如果把数据向前移动,当要移动的数据在整个数组前端时,移动的动作很大。而且当整个数组很大时,这样移动比较费资源。
就算是TStringList也是一样的,也用到了System.Move来移动数组,他毕竟不是链表。所以,我觉得你是用System.Move来移动数组,效率还是可以得。
如果是Array of integer(Shortint,SmallInt,Byte,Word,Dword,Single,Real48,Real,Extended,Pointer);可以考虑使用内存块移动,建议看看TList的Delete(Index:integer)的实现过程,如果是对TList比较熟悉,干脆用TList来保存他们的指针,用New和Dispose来管理
如果是Array of 结构,建议使用TList
==========================================================================================
引用 kiboisme(蓝色光芒) :建议看看TList的Delete(Index:integer)的实现过程,如果是对TList比较熟悉,干脆用TList来保存他们的指针,用New和Dispose来管理指针应该蛮快的,可能这个办法效率比较高。
==========================================================================================
引用 flyforlove(为情飞) :
我觉得你是用System.Move来移动数组,效率还是可以得这个方法比起上面kiboisme(蓝色光芒) 提到的方法不知效率如何呢?
Array of TEveryObject 和 Array of DWORD 是一回事。
唯一不同的是:前者在删除前需要作 ().Free
提醒楼主:
Array of TEveryObject 和 Array of DWORD 是一回事。
唯一不同的是:前者在删除前需要作 ().Free
==============================================================================
受教了。那你言下之意是除了类似Array of DWORD 结构的数组,还有其他结构的数组?请问是什么结构的呢?
我想kiboisme(蓝色光芒)的意思是让你用TList管理指针数组。
鉴于你的问题,我觉得你用TStringList就可以了,其实它的内部实现就是用的System.Move
看来大数组用指针管理应该很方便。
比如:
array of TMsg;
或者
TXXX = Record
ID : integer;
Name : String;
Sex : Boolean;
.......
end;
Array of TXXX;
flyforlove(为情飞):我想kiboisme(蓝色光芒)的意思是让你用TList管理指针数组。就是这个意思。
这样的东西结构数组,用Move来实现是非常复杂。
所以建议用TList来管理指针。
........
下面是删除第5000个数据:
Ars[5000] := Ars[High(Ars)];
SetLength(Ars,Length(Ars)-1);
就行了,最多就是判断一下数组的长度。
program Del;
{$APPTYPE CONSOLE}
uses
SysUtils;
var
a: array[1..100] of string;
i: Integer;
begin
for i:= 1 to 100 do
a[i] := IntToStr(i);
for i:=1 to 100 do
Write(a[i],' ');
Writeln; // 删除地50个字符串
Move(a[51],a[50],(100-51+1)*sizeof(String));
for i:=1 to 99 do
Write(a[i],' ');
Writeln;
Readln;
end.
如果从 TList 删除一个元素(即指针),该操作等同于从 array of pointer 中删除元素。这里提示楼主一下,array of 类 这个数组的大小 = array of pointer 。因为 Delphi 里没有对对象的引用,而只有指向对象的指针。而 array of 结构体 的大小 = sizeof(结构体) * 数组长度。
Move(a[51],a[50],(100-51+1)*sizeof(String));
这绝对是一个错误,
Array of String
实际是数组是只保存了String的指针。
你这样相当了只移动了指针,后一个指针移动到前面一个,覆盖了前一个指针,内存肯定泄露。
Sizeof(String)=4
看看这个程序:
procedure TForm1.Button1Click(Sender: TObject);
var
SS : array of String;
i : integer;
begin
Setlength(SS,2);
SS[0] := 'A';
SS[1] := 'B';
for i:=0 to 22 do
SS[0] := SS[0] + SS[0]; //让SS[0]有2^22个字符'A'
// Move(SS[1],SS[0],Sizeof(String));
SetLength(SS,0);
end;如果注释掉Move行,程序运行这个过程后,程序占用的内存,几乎不发生变化
如果是加上这行,运行这个过程后,程序占用增加了8-9M。
Move(SS[1],SS[0],Sizeof(String));后,让SS[0]原来所指向的字串躲开了Delphi的内存管理。本来String是用引用计数来管理的,现在它的计数为1,而且计数不能够减少,所以delphi也就放过它了。
对于上面那个例子。procedure TForm1.Button1Click(Sender: TObject);
var
SS : array of String;
i : integer;
begin
Setlength(SS,2);
SS[0] := 'A';
SS[1] := 'B';
for i:=0 to 22 do
SS[0] := SS[0] + SS[0]; //让SS[0]有2^22个字符'A' System.Finalize(SS[0]); //这儿加这么一句就可以了。 Move(SS[1],SS[0],Sizeof(String));
SetLength(SS,0);
end;
type
TMyArr = array of string;
var
aMyArr: TMyArr;
begin
SetLength(aMyArr, 10000);
//如果我想删除第5000个元素,如何快速的删除它?
end;==================================================================================
用内存拷贝,将5001以后的所有内容拷从5000位置开始拷贝,长度就是10000-5000
最后别忘了长度-1测试代码procedure TForm1.FormCreate(Sender: TObject);
var i:integer;
begin
SetLength(aMyArr, 10000);
for i:=0 to 9999 do
aMyArr[i]:=inttostr(i);
end;procedure TForm1.Button1Click(Sender: TObject);
begin
copymemory(@aMyArr[5000],@aMyArr[5001],5000);
SetLength(aMyArr, 9999);
showmessage(aMyArr[5000]);
showmessage(aMyArr[9998]);
showmessage(aMyArr[9999]);
end;
多谢flyforlove(为情飞)的那句:
System.Finalize(SS[0]);