比较部分字符串的最快方法是什么?

3
我需要比较一个部分字符串 "SKILL_______EU_______WAND_______CLERIC_______BASE_____01" 和 "SKILL",这是为了检查前四个字符是否为 "SKILL"。或者只检查第一个字符,这里需要优化
我的问题:
  1. 我不知道如何进行优化的比较。
  2. 它必须重复 35,000 次,所以必须非常快速。
谢谢!

6
第一个四个字怎么可能是“SKILL”?! - jason
你是在试图改述我的问题吗? - Ivan Prodanov
3
哈哈!不,我并不是试图改述你的问题。我只是指出这个字符串的前四个字符永远不会是“SKILL”。 - jason
10个回答

13

使用 StrUtils.AnsiStartsStr 进行区分大小写比较,使用 StrUtils.AnsiStartsText 进行不区分大小写的比较(将 StrUtils 添加到您的 uses 子句中)


5

如果你想要最佳速度,你需要自己编写一个小的StartsWith函数。

// untested, case-sensitive
Function StartsWith(const find, text : string) : Boolean;
var i, len : integer;
begin
   result := true;
   len := Min(Length(find), Length(text));
   For i := 1 to len do
   Begin
     if (find[i] <> text[i]) 
     then begin
       result := False;
       break;
     end;
   End;   
end;

8
Delphi已经有AnsiStartsStr(区分大小写)/AnsiStartsText(不区分大小写)函数,没有必要重新实现它。只需使用“StrUtils”单元即可。 - Andreas Hausladen
@Andreas,你说得对,我只是找不到它。只希望完整的Delphi文档在线上能够查阅... 我会留下这个答案,它可以作为自定义版本的起点。 - H H

5

如今,35000次重复并不算太多,你做什么可能并不重要。


这是一个明智的想法。以最可靠的方式完成,无论速度有多慢,然后存储结果并永远不要再做一遍。 - quillbreaker
2
尽管这种回答可能是明智的,但实际上它并没有真正回答问题,无论问题是什么。因此,我完全可以理解为什么会被投票否决。 - Rob Kennedy

2

无论您选择哪种解决方案,请记得实际测试和基准测试与您当前的实施相对比。

否则,您只是在猜测,而不是优化。

并且请注意,过早地进行优化是万恶之源

祝好运!


1

我认为Delphi程序非常优化和快速,所以只需使用它们。

var
  position : Integer;

begin
  // AnsiPos
  //   returns the position of a substring in a string
  //   or 0 if the substring isn't found
  position := AnsiPos('SKILL', 'SKILL_______EU_______WAND_______CLERIC_______BASE_____01');
end;

3
即使第一个字符不相等,这个程序将继续扫描整个域字符串。 - H H

1
如果您只想检查第一个字符,可以这样做:
if 'S' = 'SKILL_______EU_______WAND_______CLERIC_______BASE_____01'[1] then
begin
    showmessage('SKILL');
end

当然可以编译。虽然我没有在 Delphi 2009 上测试过,但我相信它可以在所有 Delphi 版本上编译。 - Nick Dandoulakis
我认为在字符串字面值上应用括号运算符是不合法的。但如果你说它可以编译,我会相信你的话。请注意,Free Pascal 接受这种语法(即使在“Delphi模式”下也是如此)。 - Rob Kennedy

0
为什么不这样做:
function StartsWith( const AMatchStr, ATestStr : string ) : boolean;
begin
  Result := SameText( AMatchStr, copy( ATestStr, 1, Length( AMatchStr ));
end;

这将不会处理 ATestStr 的起始文本之外的任何部分。Bri


但它将复制字符,这并不是严格必要的。 - H H
1
为什么不这样做?因为该库已经带有这样的功能,即使没有也最好使用StrLComp而不是制作字符串的临时副本。 - Rob Kennedy

0
如果你只想检查前4/5个字符,可以这样做:
i:= Length('SKILL');

LeftStr('SKILL_______EU_______WAND_______CLERIC_______BASE_____01',i) = 'SKILL'

0
if AnsiPos('SKILL', 'SKILL_______EU_______WAND_______CLERIC_______BASE_____01') > 0 then

我认为这应该可以完成工作,但我不了解 AnsiPos 的速度,它是快还是慢或其他什么情况。每当我想要比较字符串的片段时,它对我很有效。AnsiPos() 返回一个整数值,表示您要查找的字符串的起始索引。


0

我对Delphi不是很了解,但我认为(在任何语言/框架/平台上)正则表达式是最快的字符串扫描方式...

您并没有明确指定您要搜索的所有条件...


1
正则表达式非常全面,但它们并不以速度著称。你应该将正则表达式用于复杂的搜索,而不是琐碎的搜索,特别是如果速度至关重要。 - Lepidosteus
1
“not reputed to be fast at all” - 你有相关链接吗?大多数正则表达式的匹配时间复杂度为O(n),很难用手写代码超越它们。 - H H
2
@Henk Holterman:抱歉我应该更具体一些;像这个问题中的那种情况要求快速。如果你只是想检查字符串的前4-5个字符是否与某些内容匹配,最好使用专门设计和优化过的函数来完成。 - Lepidosteus
这就是为什么我说他没有指定所有的条件! - Denis Biondic

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接