procedure RemoveRecord(Index: integer);
begin
FRecords[Index]:= FRecords[High(FRecords)]; { Copy the last element over the 'deleted' element }
SetLength(FRecords, Length(FRecords)-1); { Cut the last element }
end;
{ I haven't tested the code to see it compiles, but you got the idea anyway... }
8条答案
按热度按时间mznpcxlj1#
在此之前,我演示了如何从动态数组中删除项:
在那篇文章中,我从以下代码开始:
使用该代码,您“不会出错”。为
X
使用您想要的任何值;在您的情况下,将其替换为string
。如果你想变得更花哨,使用Move
,那么也有办法做到这一点。由于
X
是string
,因此Finalize
调用等同于将空字符串赋给该数组元素。不过,我在这段代码中使用Finalize
,因为它适用于所有数组元素类型,甚至包括记录、接口、字符串和其他数组的类型。对于插入,您只需将事物移动到相反的方向:
当您要执行超出语言范围的操作时,请使用
Finalize
,例如使用非类型安全的Move
过程覆盖编译器托管类型的变量。当您重新输入语言的定义部分时,请使用Initialize
。(该语言定义了使用SetLength
扩展或缩小数组时发生的情况,但它不定义如何在不使用字符串赋值语句的情况下复制或删除字符串。)xlpyo6sf2#
您没有说明保持数组元素的顺序是否重要。如果顺序不相关,你可以像这样做非常非常快:
列表排序
如果您有一个庞大的列表需要用户修改,您可以使用类似于上面的方法(打破列表顺序)。当用户完成编辑(在多次删除之后)时,您向其显示一个名为“Sort List”的按钮。现在他可以做冗长的(排序)操作了。
当然,上面我假设您的列表可以按某个参数进行排序。
列表自动排序
另一种选择是自动执行分拣过程。当用户从列表中删除内容时,启动计时器。如果用户不断删除项目,请继续重置计时器。当计时器设法触发事件时,执行排序,停止计时器。
v1uwarro3#
要插入字符串,只需在数组(指针数组)的末尾添加一个字符串(惰性方法),然后使用
Move
更改该数组(指针数组)的元素顺序。hmtdttj44#
如果我想在字符串列表的中间插入一个字符串,我会使用TStringList.Insert。(它使用System.Move快速完成此操作。)
使用数组而不是TStringList有什么特别的原因吗?
fkvaft9z5#
在处理它之前,对它调用UniqueString()。
http://docwiki.embarcadero.com/VCL/en/System.UniqueString
然后,您就有了一个只有一个引用的字符串。
DELETE和INSERT也不太可能做到这一点,而且我怀疑你会更快。
mnemlml86#
只是想为将来来这里的任何人添加这一点。
修改Rob的代码时,我想出了一种使用较新的
TArray<T>
类型结构的方法。对于插入物也可以做类似的事情。
(我并不希望这个答案被标记为答案,只是希望提供一个太长的例子,无法放入对Rob优秀答案的评论中。)
(已修复以回应Rob下面的评论。)
n7taea2i7#
Move()可以很好地处理引用计数的类型,如字符串或接口,并且实际上在Delphi的数组和列表中内部使用。但是,在一般情况下,由于管理记录功能,move()不再有效。
62lalag48#
如果您使用System.Move将项放入字符串数组中,您应该注意到,在移动之前(现在被覆盖)的字符串具有引用计数-1(对于常量字符串),或者>0(对于变量字符串)。不应该更改常量字符串,但应该相应地处理变量字符串:您应该手动降低它们的引用计数(在它们被覆盖之前!)。要做到这一点,您应该尝试如下所示:
但是,如果引用计数达到零,您还应该终止相关的内存-如果让它工作,Delphi本身就会做得更好-它是字符串的编译器魔术。哦,还有:如果您要复制的字符串与您要写入的字符串来自同一个数组,那么所需的管理将变得非常麻烦,而且非常快!
因此,如果以某种方式可以避免所有这些手动内务,我建议让Delphi自己处理。