Reputation: 1427
I want to count how many times a String occurs in another String in Pascal Script like shown in the below example.
I've seen the answer to Delphi: count number of times a string occurs in another string, but there is no PosEx
function in Pascal Script.
MyString := 'Hello World!, Hello World!, Hello World!, Hello World!';
If I count the number of times Hello
or World
occurs here, the result should be 4.
If I count the number of times ,
(comma) occurs here, the result should be 3.
UPDATE
The following function works, but it copies given String again to a new Variable, and deletes parts of Strings, so it works slowly.
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;
Upvotes: 2
Views: 1429
Reputation: 202534
Your implementation is generally correct.
There are some optimizations to be made and useless code to be removed:
if Pos(SubStr, S) <> 0
(within repeat
) is pointless. It's true always. You are testing S
, which was tested at the function start already. And the DSStr
is already tested in the until
.Pos(SubStr, DSStr)
to a variable not to call it multiple times.Length(Copy(DSStr, Pos(SubStr, DSStr), Length(SubStr)))
is actually the same as Length(SubStr)
.S
to DSStr
. You can work directly with the S
. It's by-value parameter, so you do not modify the variable that you use to call the function.Pos(SubStr, S) = 0
check with the same check in the loop to save one Pos
call.Optimized version of your code:
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;
But actually with the Inno Setup StringChange
function (which Delphi does not have), you do not have to code any algorithm yourself.
function OccurrencesOfSubString(S, SubStr: String): Integer;
begin
Result := StringChange(S, SubStr, '');
end;
This was inspired by the @RobertFrank's answer to Delphi: count number of times a string occurs in another string.
While the use of the StringChange
looks inefficient (as it has significant side effects), it's actually faster. Probably because it is implemented in Pascal, not in Pascal Script.
Tested with 3 million calls to:
OccurrencesOfSubString('Hello World!, Hello World!, Hello World!, Hello World!', 'Hello')
StringChange
: 11 secondsThough for few calls, all implementations are good enough.
Upvotes: 3