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!';
如果我统计这里出现Hello
或World
的次数,结果应该是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秒
虽然很少调用,但所有实现都足够好。
我想计算一个字符串在 Pascal 脚本中的另一个字符串中出现的次数,如下例所示。
我看过 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。
更新
下面的函数可以运行,但是它会将给定的字符串再次复制到一个新的变量中,并删除部分字符串,因此运行速度较慢。
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秒
虽然很少调用,但所有实现都足够好。