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

Pascal Script Count number of times a string occurs in another string

我想计算一个字符串在 Pascal 脚本中的另一个字符串中出现的次数,如下例所示。

我看过 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。

更新

下面的函数可以运行,但是它会将给定的字符串再次复制到一个新的变量中,并删除部分字符串,因此运行速度较慢。

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;

您的实施大体上是正确的。

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

  • 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。它是按值参数,因此您无需修改​​用于调用函数的变量。
  • 用循环中的相同检查替换初始 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 Script 中实现的。

经过 300 万次调用测试:

OccurrencesOfSubString('Hello World!, Hello World!, Hello World!, Hello World!', 'Hello')
  • StringChange:11 秒
  • 我的代码优化版本:49 秒
  • 你的原码:99秒

虽然很少调用,但所有实现都足够好。