我想计算一下String在Pascal脚本中的另一个String中出现的次数,如下例所示。
我已经看到了Delphi: count number of times a string occurs in another string的答案,但Pascal脚本中没有PosEx
函数。
MyString := 'Hello World!, Hello World!, Hello World!, Hello World!';
如果我计算此处出现Hello
或World
的次数,则结果应为4.
如果我计算,
(逗号)出现在这里的次数,结果应为3。
更新
以下函数有效,但它会将给定的String再次复制到一个新的Variable,并删除部分字符串,因此它的工作速度很慢。
function OccurrencesOfSubString(S, SubStr: String): Integer;
var
DSStr: String;
begin
if Pos(SubStr, S) = 0 then
Exit
else
DSStr := S;
Repeat
if Pos(SubStr, S) <> 0 then
Inc(Result);
Delete(DSStr, Pos(SubStr, DSStr), Length(Copy(DSStr, Pos(SubStr, DSStr), Length(SubStr))));
Until Pos(SubStr, DSStr) = 0;
end;
答案 0 :(得分:3)
您的实施通常是正确的。
要进行一些优化并删除无用的代码:
if Pos(SubStr, S) <> 0
(repeat
内)的第二次测试毫无意义。这总是如此。您正在测试S
,它已在功能启动时进行了测试。 DSStr
已经在until
。Pos(SubStr, DSStr)
保存到变量中,而不是多次调用它。Length(Copy(DSStr, Pos(SubStr, DSStr), Length(SubStr)))
实际上与Length(SubStr)
相同。S
复制到DSStr
。您可以直接使用S
。它是by-value参数,因此您不需要修改用于调用函数的变量。Pos(SubStr, S) = 0
支票,以保存一次Pos
电话。优化版代码:
function OccurrencesOfSubString(S, SubStr: String): Integer;
var
P: Integer;
begin
Result := 0;
repeat
P := Pos(SubStr, S);
if P > 0 then
begin
Inc(Result);
Delete(S, P, Length(SubStr));
end;
until P = 0;
end;
但实际上使用Inno Setup StringChange
function(Delphi没有),您不必自己编写任何算法代码。
function OccurrencesOfSubString(S, SubStr: String): Integer;
begin
Result := StringChange(S, SubStr, '');
end;
这受到了@RobertFrank's answer to Delphi: count number of times a string occurs in another string。
的启发虽然StringChange
的使用看起来效率低(因为它有明显的副作用),但它实际上更快。可能是因为它是用Pascal实现的,而不是Pascal脚本。
测试了300万次:
OccurrencesOfSubString('Hello World!, Hello World!, Hello World!, Hello World!', 'Hello')
StringChange
:11秒虽然很少有电话,但所有实施都足够好。