Существует ли эффективная функция поиска по всему слову в Delphi?

StackOverflow https://stackoverflow.com/questions/1678572

  •  16-09-2019
  •  | 
  •  

Вопрос

В 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;

где:

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

Мне это нужно только для того, чтобы вернуть значение true или false, если "Слово" находится в строке.

Где-то должно быть что-то для этого, потому что в стандартном диалоговом окне поиска есть "Сопоставлять только целое слово" в качестве одного из вариантов.

Как это обычно (или лучше всего) реализуется?


Заключение:

Ответ РУЗ был идеальным.Процедура SearchBuf была как раз тем, что мне было нужно.Я даже могу зайти в процедуру StrUtils, извлечь код и изменить его в соответствии с моими требованиями.

Я был удивлен, обнаружив, что 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]);

Пока.

Другие советы

Просто потому, что редактор Delphi имеет функцию "сопоставления слов", это не значит, что библиотека Delphi предлагает ее!

Как правило, в большинстве языков для этого используется регулярное выражение.Похоже, они (все еще) не встроены в Delphi, поскольку существуют сторонние библиотеки, предлагающие такую возможность.Первый пример, который я нашел, это: http://delphi.about.com/od/toppicks/tp/delphi-regular-expressions.htm .

Обычно вы создаете регулярное выражение примерно так

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

Вы захотите получить подробную информацию из документации к библиотеке, которую вы получаете.В моем примере неправильно обрабатывается регистр слова, начинающегося в начале Str или заканчивающегося в его конце, или являющегося всем Str.

Эта функция не совсем то, что вам нужно, но она довольно близка к этому:

Я надеюсь, что это полезно:

{ 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;

Если у вас есть функция, подобная приведенной ниже

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;
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top