Pascal Script计算字符串在另一个字符串中出现的次数

时间:2016-10-07 00:30:23

标签: inno-setup pascalscript

我想计算一下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!';

如果我计算此处出现HelloWorld的次数,则结果应为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;

1 个答案:

答案 0 :(得分:3)

您的实施通常是正确的。

要进行一些优化并删除无用的代码:

  • if Pos(SubStr, S) <> 0repeat内)的第二次测试毫无意义。这总是如此。您正在测试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秒
  • 我的优化版代码:49秒
  • 您的原始代码:99秒

虽然很少有电话,但所有实施都足够好。