Delphi中有高效的全词搜索功能吗?

发布于 2024-08-09 13:51:07 字数 792 浏览 1 评论 0原文

在 Delphi 2009 或更高版本(Unicode)中,是否有任何内置函数或小例程编写在某处,可以进行相当有效的全单词搜索,其中您提供定义单词的分隔符,例如:

function ContainsWord(Word, Str: string): boolean;

const  { Delim holds the delimiters that are on either side of the word }
  Delim = ' .;,:(){}"/\<>!?[]'#$91#$92#$93#$94'-+*='#$A0#$84;

where:

Word: string;  { is the Unicode string to search for }
Str: string;   { is the Unicode string to be searched }

我只需要它返回如果“Word”在字符串中,则为 true 或 false 值。

某个地方一定有这样的东西,因为标准查找对话框将“仅匹配整个单词”作为其选项之一。

通常(或最好)如何实施?


结论:

RRUZ的回答很完美。 SearchBuf 例程正是我所需要的。我什至可以进入 StrUtils 例程,提取代码并修改它以满足我的要求。

我惊讶地发现 SearchBuf 并不是先搜索单词,然后检查分隔符。相反,它一次遍历字符串中的一个字符来查找分隔符。如果找到,则会检查字符串和另一个分隔符。如果没有找到,它就会寻找另一个分隔符。为了效率,这非常聪明!

In Delphi 2009 or later (Unicode), are there any built-in functions or small routines written somewhere that will do a reasonably efficient whole word search where you provide the delimiters that define the word, e.g.:

function ContainsWord(Word, Str: string): boolean;

const  { Delim holds the delimiters that are on either side of the word }
  Delim = ' .;,:(){}"/\<>!?[]'#$91#$92#$93#$94'-+*='#$A0#$84;

where:

Word: string;  { is the Unicode string to search for }
Str: string;   { is the Unicode string to be searched }

I only need this to return a true or false value if the "Word" is in the string.

There must be something for this somewhere, because the standard Find Dialog has "Match whole word only" as one of it's options.

How is this normally (or best) implemented?


Conclusion:

RRUZ's answer was perfect. The SearchBuf routine was just what I needed. I can even go into the StrUtils routine, extract the code, and modify it to fit my requirements.

I was surprised to find that SearchBuf doesn't first search for the word and then check for delimiters. Instead it goes through the characters of the string one at a time looking for a delimiter. If it finds one, then it checks for the string and another delimiter. If it doesn't find it, it then looks for another delimiter. For efficiency's sake, that's very smart!

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(4

瀟灑尐姊 2024-08-16 13:51:07

您可以将 SearchBuf 函数与 [soWholeWord] 选项结合使用。

function SearchBuf(Buf: PAnsiChar; BufLen: Integer; SelStart: Integer; SelLength: Integer; SearchString: AnsiString; Options: TStringSearchOptions): PAnsiChar;

请参阅此示例

function ExistWordInString(aString:PWideChar;aSearchString:string;aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
Begin
      Size:=StrLen(aString);
      Result := SearchBuf(aString, Size, 0, 0, aSearchString, aSearchOptions)<>nil;
End;

按此方式使用

ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);

再见。

You can use the SearchBuf function with the [soWholeWord] option.

function SearchBuf(Buf: PAnsiChar; BufLen: Integer; SelStart: Integer; SelLength: Integer; SearchString: AnsiString; Options: TStringSearchOptions): PAnsiChar;

See this example

function ExistWordInString(aString:PWideChar;aSearchString:string;aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
Begin
      Size:=StrLen(aString);
      Result := SearchBuf(aString, Size, 0, 0, aSearchString, aSearchOptions)<>nil;
End;

Use it this way

ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);

Bye.

狼亦尘 2024-08-16 13:51:07

仅仅因为 Delphi 的编辑器具有“单词匹配”功能,并不意味着 Delphi 库提供它!

通常,在大多数语言中,实现此目的的方法是使用正则表达式。似乎它们(仍然)没有内置到 Delphi 中,因为有第 3 方库提供了该功能。我找到的第一个例子是: http://delphi.about .com/od/toppicks/tp/delphi-regular-expressions.htm

通常,您会构建一个正则表达式,例如

myRegex = '[' + Delim + ']+' + Word + '[' + Delim + ']+';
if regexSearch (Str, myRegex) then ...

您将希望从您获得的库的文档中获取详细信息。我的示例无法正确处理单词从 Str 开头开始、在其末尾结束、或者全部为 Str 的情况。

Just because Delphi's editor has a "word match" function, that doesn't mean the Delphi library offers it!

Typically, in most languages the way to go for this is a regular expression. Seems they're (still) not built into Delphi, as there are 3rd party libraries offering the capability. The first example I found is: http://delphi.about.com/od/toppicks/tp/delphi-regular-expressions.htm .

Typically, you'd build a regular expression something like

myRegex = '[' + Delim + ']+' + Word + '[' + Delim + ']+';
if regexSearch (Str, myRegex) then ...

You'll want to get details from the documentation of the library you get. My example doesn't correctly handle the case of the word starting at the beginning of Str or ending at its end, or being all of Str.

放血 2024-08-16 13:51:07

如果你有像下面这样的函数

function ExistWordInString(aString:PWideChar;aSearchString:string;aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
Begin
      Size:=StrLen(aString);
      Result := SearchBuf(aString, Size, 0, 0, aSearchString, aSearchOptions)<>nil;
End;

并这样调用它:

ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);

如果你调用它一次,你可能不会遇到任何问题。但是,如果您在循环中调用它(例如 1000 次或更多),首先使用 Pos 函数(如下所示)将令人惊讶地为您带来额外的性能

function ExistWordInString(const AString:string;const ASearchString:string;ASearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
  AWChar: PWideChar;
begin
   if Pos(LowerCase(ASearchString), LowerCase(AString)) = 0 then
   begin
      Exit(False);
   end;

   AWChar := PWideChar(AString);
   Size:=StrLen(AWChar);
   Result := SearchBuf(AWChar, Size, 0, 0, ASearchString, ASearchOptions)<>nil;
end;

If you have function like below

function ExistWordInString(aString:PWideChar;aSearchString:string;aSearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
Begin
      Size:=StrLen(aString);
      Result := SearchBuf(aString, Size, 0, 0, aSearchString, aSearchOptions)<>nil;
End;

and call it like this:

ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);

You may not fell any problem if you call it once. But if you call this in a loop (for example 1000 times or more) first using Pos function (like below) will surprisingly give you extra performance

function ExistWordInString(const AString:string;const ASearchString:string;ASearchOptions: TStringSearchOptions): Boolean;
var
  Size : Integer;
  AWChar: PWideChar;
begin
   if Pos(LowerCase(ASearchString), LowerCase(AString)) = 0 then
   begin
      Exit(False);
   end;

   AWChar := PWideChar(AString);
   Size:=StrLen(AWChar);
   Result := SearchBuf(AWChar, Size, 0, 0, ASearchString, ASearchOptions)<>nil;
end;
风吹雨成花 2024-08-16 13:51:07

这个函数并不完全是您所需要的,但它非常接近:

我希望它有用:

{ Copy all whole words from MainStr. The result will not have more than MaxChars characters. }

function CopyWords(MainStr: string; MaxChars: Integer): string;   
VAR EndsInSpace: Boolean;
    EndString, i: Integer;
    NextChar: char;
begin
 Assert(MaxChars > 0);
 EndString:= MaxChars;

 if Length(MainStr) > MaxChars then
  begin
   NextChar:= mainstr[MaxChars+1];

   if (MainStr[MaxChars] <> ' ') AND (NextChar <> ' ')
   then
     begin
      for i:= MaxChars downto 1 DO
       if MainStr[i]= ' ' then
        begin
         EndString:= i;
         Break;
        end
     end
   else
    if (MainStr[MaxChars]  = ' ')
    OR (MainStr[MaxChars] <> ' ') AND (NextChar = ' ')
    then EndString:= MaxChars;
  end;

 Result:= CopyTo(MainStr, 1, EndString);
 Result:= TrimRight(Result);
end;

This function is not exactly what you need but it is pretty close:

I hope it is useful:

{ Copy all whole words from MainStr. The result will not have more than MaxChars characters. }

function CopyWords(MainStr: string; MaxChars: Integer): string;   
VAR EndsInSpace: Boolean;
    EndString, i: Integer;
    NextChar: char;
begin
 Assert(MaxChars > 0);
 EndString:= MaxChars;

 if Length(MainStr) > MaxChars then
  begin
   NextChar:= mainstr[MaxChars+1];

   if (MainStr[MaxChars] <> ' ') AND (NextChar <> ' ')
   then
     begin
      for i:= MaxChars downto 1 DO
       if MainStr[i]= ' ' then
        begin
         EndString:= i;
         Break;
        end
     end
   else
    if (MainStr[MaxChars]  = ' ')
    OR (MainStr[MaxChars] <> ' ') AND (NextChar = ' ')
    then EndString:= MaxChars;
  end;

 Result:= CopyTo(MainStr, 1, EndString);
 Result:= TrimRight(Result);
end;
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文