我经常发现我需要'调整'一个TStringList
来调整N个元素,或者在列表中添加额外的空字符串,或者删除不必要的字符串。
在C ++ STL容器上,我可以使用resize
方法,但由于这似乎不存在,我通常会做这样的事情(警告:伪代码!)。
list.beginUpdate;
while list.Count < requiredSize do
begin
list.add('');
end;
while list.Count > requiredSize do
begin
list.delete(list.count-1);
end;
list.endUpdate;
有没有一种更为简单的方法可以忽略这一点?
答案 0 :(得分:6)
从TStringList.Assign
的实施情况来看,没有更好的方法可以做到这一点。他们基本上会调用Clear
并逐个添加字符串。
您当然应该将代码放入实用程序方法中:
procedure ResizeStringList(List : TStrings; ANewSize: Integer);
begin
...
end;
或者您可以使用类帮助程序使您的方法看起来是TStringList
本身的一部分。
答案 1 :(得分:3)
您问题中的方法是您可以做的最好的方法。如果使用类助手,可以使其更清晰。例如:
type
TStringsHelper = class helper for TStrings
procedure SetCount(Value: Integer);
end;
procedure TStringsHelper.SetCount(Value: Integer);
begin
BeginUpdate;
try
while Count<Value do
Add('');
while Count>Value do
Delete(Count-1);
finally
EndUpdate;
end;
end;
然后你可以写:
List.SetCount(requiredSize);
答案 2 :(得分:3)
Capacity
属性几乎是理想的,因为它将在内部数组中分配正确数量的条目。然而,它有一个令人遗憾的缺点:
Strings.Count
未更新。由于Delphi组件体系结构引用了基类型TStrings
,因此您可以提供可以支持更高效的大小调整功能的具体子类。例如。考虑TList.SetCount
的以下实现。
procedure TList.SetCount(NewCount: Integer);
var
I: Integer;
begin
if (NewCount < 0) or (NewCount > MaxListSize) then
Error(@SListCountError, NewCount);
if NewCount > FCapacity then
SetCapacity(NewCount);
if NewCount > FCount then
FillChar(FList^[FCount], (NewCount - FCount) * SizeOf(Pointer), 0)
else
for I := FCount - 1 downto NewCount do
Delete(I);
FCount := NewCount;
end;
更新容量后,如果有新分配的内存,则使用FillChar
进行初始化。这比一次添加/删除一个项目更有效。
因此,您可以提供自己的TStrings
子类的独立具体实现,或者只是复制Delphi的TStringList
,其中包含适当的SetCount
方法。
但是,我发现这部分代码不太可能遇到任何性能问题,因此用适当的实用方法包装的自己的解决方案就足够了。 David's answer也很好,但我个人并不认为“类助手”功能非常有用。实施班助手的“老方法”更加通用。
答案 3 :(得分:0)
var
List: TStringList;
Assert(requiredSize >= 0);
if requiredSize > List.Count then
List.Capacity := requiredSize
else
while List.Count > requiredSize do
List.Delete(List.Count - 1);