Alo*_*mer 4 delphi delphi-2006
我需要将字符串拆分为具有固定长度子字符串的TStringList.
目前我使用:
procedure StrToStringList(ASource: string; AList: TStrings; AFixedLen: Integer);
begin
Assert(Assigned(AList));
while Length(ASource) > AFixedLen do
begin
AList.Add(LeftStr(ASource, AFixedLen));
Delete(ASource, 1, AFixedLen);
end;
AList.Add(ASource);
end;
Run Code Online (Sandbox Code Playgroud)
这有效,但似乎很慢.有更好/更快的想法吗?
编辑:结果分析:
速度提升令人印象深刻.以下是我(主观)剖析的结果.
数据大小:290KB,FixedLen:100:
数据大小:2805KB,FixedLen:100:
我认为修改输入字符串是浪费的.避免这样这样:
var
Remaining: Integer;
StartIndex: Integer;
begin
Remaining := Length(ASource);
StartIndex := 1;
while Remaining > 0 do
begin
AList.Add(Copy(ASource, StartIndex, AFixedLen));
inc(StartIndex, AFixedLen);
dec(Remaining, AFixedLen);
end;
end;
Run Code Online (Sandbox Code Playgroud)
这将减少堆分配和复制的数量.
但是,如果你观察到性能上没什么好处,我也不会感到惊讶.为了执行任何严肃的优化,我们可能需要查看一些示例输入数据.
您的代码中可能会立即显示一些明显的优化:
不要修改源字符串,只需提取所需的子字符串.然后,您可以使输入字符串参数为const,从而允许编译器进一步优化对该过程的调用
由于您正在处理固定长度和已知长度的输入字符串,因此您可以预先计算字符串列表所需的容量,并在添加列表时避免重新分配内存.
以下是我将如何做到这一点:
procedure StrToStringList(const aSource: String;
const aList: TStrings;
const aFixedLen: Integer);
var
idx: Integer;
srcLen: Integer;
begin
aList.Capacity := (Length(aSource) div aFixedLen) + 1;
idx := 1;
srcLen := Length(aSource);
while idx <= srcLen do
begin
aList.Add(Copy(aSource, idx, aFixedLen));
Inc(idx, aFixedLen);
end;
end;
Run Code Online (Sandbox Code Playgroud)
这里的容量计算可能导致容量过剩1,其中输入字符串精确地除以固定长度,但这是一个可忽略的开销,并且在目标是最佳性能的情况下是可接受的(替代方案是修改或计算的条件分支)容量不同,以满足可能少数情况下的情况).
| 归档时间: |
|
| 查看次数: |
1739 次 |
| 最近记录: |