I need to know if all characters in a string are equal (formed by the same character). the function must return true or false depending if all the elements of the string are equal to an particular char.
I wrote this function that works well, but I'm looking for a more optimal (fastest) solution, the strings can have thousands of chars.
function AllElementsAreEqual(Element:Char;Str:String):Boolean; var i : Integer; begin Result:=True; if Str<>'' then for i:=1 to Length(Str) do if Str[i]<>Element then begin Result:= False; exit; end; end;
UPDATE finally using the Barry Kelly Suggestion and adding the
inline directive, the performance was significantly improved.
function AllElementsAreEqual(Const Element:Char;Str:String):Boolean;inline; type ArrayInt = Array of Integer; var i : Integer; Delta: Integer; List : ArrayInt; Test : Integer; begin Result:=True; Delta:=(Length(Str) mod 4); if Delta<>0 then Str:=Str+StringOfChar(Element,4-Delta); Test:=Ord(Element) + Ord(Element) shl 8 + Ord(Element) shl 16 + Ord(Element) shl 24; List:=ArrayInt(@(Str)); for i:=0 to ((Length(Str) div 4)-1) do if List[i]<>Test then begin Result:=False; exit; end; end;
i'm sorry but i posted an old implementation of the solution (with a bug), now is fixed. Thanks to The_Fox for create a better implementation of the Barry suggestion.
You could consider creating an
Integer value with the
Element repeated 4 times (since this is
AnsiChar in Delphi 7), shifted like
Ord(Element) + Ord(Element) shl 8 + Ord(Element) shl 16 + Ord(Element) shl 24, then typecast the string to a
^array[0..MaxInt div 4 - 1] of Integer) and loop over it
Length(Str) div 4 times, comparing as integers instead of characters. You'll need to compare the last few
Length(str) mod 4 characters manually though.