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

时间:2010-10-06 04:37:44

标签: 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;

更新 最后使用Barry Kelly建议并添加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;

更新2

我很抱歉,但我发布了一个旧的解决方案实施(带有一个错误),现在已修复。 感谢The_Fox更好地实施了Barry建议。

6 个答案:

答案 0 :(得分:9)

您可以考虑创建一个Integer值,Element重复4次(因为这是Delphi 7中的AnsiChar),转移为Ord(Element) + Ord(Element) shl 8 + Ord(Element) shl 16 + Ord(Element) shl 24,然后对字符串进行类型转换到PIntegerArray^array[0..MaxInt div 4 - 1] of Integer)并循环Length(Str) div 4次,比较为整数而不是字符。您需要手动比较最后几个Length(str) mod 4个字符。

答案 1 :(得分:6)

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

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

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

另一个危险的事情是让动态数组(整数数组)指向一个字符串。两者都被重新计算,这可能会导致奇怪的结果。请遵循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;

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

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

答案 2 :(得分:0)

也许使用StringOfChar生成一个目标字符串重复N次的字符串,然后进行字符串比较而不是比较char-by-char。

(不知道这实际上是否更快;测量和看到)。

答案 3 :(得分:0)

您可以实现Select algorithm以更快地找到char,这不会增加字符串为“True”的速度,但它应该使它更快一些。

答案 4 :(得分:0)

获取字符串长度,使用GetMem为字符串大小分配内存。 FillChar带有所需char的内存。然后使用CompareMem比较字符串和内存

答案 5 :(得分:-3)

根据我的代码理解

Result:= False;

:= ”用于为变量赋值。你如何比较delphi中的2个值?