如何确定字符串中的所有字符是否相等

Sal*_*dor 5 delphi string delphi-7

我需要知道,如果在一个字符串中的所有字符都相等(由相同的字符组成).函数必须返回true或false,具体取决于字符串的所有元素是否等于特定的char.

我写了这个功能很好,但我正在寻找一个更优化(最快)的解决方案,字符串可以有数千个字符.

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;
Run Code Online (Sandbox Code Playgroud)

UPDATE 最终使用了Barry Kelly Suggestion并添加了inline指令,性能得到了显着提升.

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[1]));

  for i:=0 to ((Length(Str) div 4)-1) do
   if List[i]<>Test  then
    begin
     Result:=False;
     exit;
    end;
end;
Run Code Online (Sandbox Code Playgroud)

更新2

对不起,但是我发布了一个旧的解决方案实现(有一个bug),现在已修复.感谢The_Fox创建了更好的Barry建议实现.

Bar*_*lly 9

您可以考虑重复创建一个IntegerElement4次(因为这是AnsiChar在Delphi 7中),移位Ord(Element) + Ord(Element) shl 8 + Ord(Element) shl 16 + Ord(Element) shl 24,然后将字符串强制转换为a PIntegerArray(^array[0..MaxInt div 4 - 1] of Integer)并循环遍历它Length(Str) div 4,比较为整数而不是字符.您需要Length(str) mod 4手动比较最后几个字符.


The*_*Fox 6

你实施了巴里凯利错误的建议.当我在Delphi 7上测试它时,它甚至比你的第一次实现慢,如果你的stringlength不能被4整除,它会得到错误的结果.

我用这个字符串测试了它:StringOfChar('c', 100000) + 'x';你的新函数返回True AllElementsAreEqual('c', StringOfChar('c', 100000) + 'x'),它应该返回False.

你的实现速度较慢,因为你试图将你的字符串除以4(你失败了,但你可以自己弄清楚它失败的原因),从而创建一个需要内存分配的新字符串.

另一个危险的事情是让动态数组(整数数组)指向一个字符串.两者都被重新计算,这可能会导致奇怪的结果.请关注Barry Kelly的建议并使用PIntegerArray!

我认为Barry Kelly的意思是:

function AllElementsAreEqual(const aElement: Char; const aStr: string): Boolean;
var
  lIntArray: PIntegerArray;
  i: Integer;
  lTest: Integer;
begin
  Result := True;
  lTest := Ord(aElement) + Ord(aElement) shl 8 + Ord(aElement) shl 16 + Ord(aElement) shl 24;

  lIntArray := @aStr[1];
  for i := 0 to Length(aStr) div 4 - 1 do
    if lIntArray[i] <> lTest then
    begin
      Result := False;
      Exit;
    end;

  for i := Length(aStr) - (Length(aStr) mod 4) + 1 to Length(aStr) do
    if aStr[i] <> aElement then
    begin
      Result := False;
      Exit;
    end;
end;
Run Code Online (Sandbox Code Playgroud)

注意:你的函数为空字符串返回True,是吗?

NB2:请给Barry Kelly的回答而不是我的回答,因为这真的是一个超大的评论,而不是答案.