Existe uma eficiente Whole Word Search Função em Delphi?
Pergunta
Em Delphi 2009 ou posterior (Unicode), há algum built-in funções ou pequenas rotinas em algum lugar que irá fazer uma pesquisa palavra inteira razoavelmente eficiente onde você fornecer os delimitadores que definem a palavra, por exemplo escrito:.
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;
Onde:
Word: string; { is the Unicode string to search for }
Str: string; { is the Unicode string to be searched }
Eu só preciso disso para retornar um valor verdadeiro ou falso se a "Palavra" é na cadeia.
Deve haver algo para isso em algum lugar, porque o Find padrão de diálogo tem "Match somente palavra inteira", como uma das suas opções.
Como isso é normalmente (ou melhor) implementado?
Conclusão:
A resposta de RRUZ foi perfeito. A rotina SearchBuf era exatamente o que eu precisava. Posso até ir para a rotina StrUtils, extrair o código e modificá-lo para caber minhas necessidades.
Fiquei surpreso ao descobrir que SearchBuf não primeiro procurar a palavra e, em seguida, verificar se há delimitadores. Em vez disso, passa os personagens da uma corda de cada vez à procura de um delimitador. Se encontrar um, em seguida, ele verifica para a cadeia e outro delimitador. Se não encontrá-lo, em seguida, olha para o outro delimitador. Pelo amor de eficiência, que é muito inteligente!
Solução
Você pode usar o href="http://docwiki.embarcadero.com/Libraries/XE2/en/System.StrUtils.SearchBuf" rel="nofollow noreferrer"> SearchBuf função com o [ soWholeWord] opção.
function SearchBuf(Buf: PAnsiChar; BufLen: Integer; SelStart: Integer; SelLength: Integer; SearchString: AnsiString; Options: TStringSearchOptions): PAnsiChar;
Veja este exemplo
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-lo desta maneira
ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);
Bye.
Outras dicas
Só porque editor do Delphi tem uma função "palavra jogo", isso não significa que os Delphi biblioteca oferece-lo!
Normalmente, na maioria dos idiomas o caminho a percorrer para isso é uma expressão regular. Parece que eles estão (ainda) não incorporado Delphi, pois existem bibliotecas 3o partido que oferecem a capacidade. O primeiro exemplo que encontrei é: http: //delphi.about .com / od / toppicks / tp / delphi regular-expressions.htm .
Normalmente, você iria construir uma expressão de algo regular como
myRegex = '[' + Delim + ']+' + Word + '[' + Delim + ']+';
if regexSearch (Str, myRegex) then ...
Você vai querer obter detalhes da documentação da biblioteca que você começa. Meu exemplo não manipula corretamente o caso da palavra a partir do início de str ou terminando no seu fim, ou sendo todas Str.
Esta função não é exatamente o que você precisa, mas é muito próximo:
Espero que seja útil:
{ 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;
Se você tem função como abaixo
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;
e chamá-lo assim:
ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);
Você pode não caiu nenhum problema se você chamá-lo uma vez. Mas se você chamar isso em um loop (por exemplo, 1000 vezes ou mais), primeiro usando a função Pos (como abaixo) vai surpreendentemente dar-lhe um desempenho extra
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;