¿Existe una eficiente Palabra completa Función de búsqueda en Delphi?
Pregunta
En Delphi 2009 o posterior (Unicode), ¿existen funciones incorporadas o pequeñas rutinas escritas en alguna parte que va a hacer un razonablemente eficiente búsqueda de la palabra entera en que proporciona los delimitadores que definen la palabra, por ejemplo:.
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;
donde:
Word: string; { is the Unicode string to search for }
Str: string; { is the Unicode string to be searched }
Yo sólo necesito esto para devolver un valor verdadero o falso si la "Palabra" se encuentra en la cadena.
Tiene que haber algo de esto en alguna parte, porque el estándar de diálogo Encontrar ha "coincidir sólo palabras completas" como una de sus opciones de.
¿Cómo es esto normalmente (o mejor) implementado?
Conclusión:
La respuesta de RRUZ era perfecto. La rutina SearchBuf era justo lo que necesitaba. Incluso puedo entrar en la rutina StrUtils, extraer el código y modificarlo para satisfacer mis necesidades.
Me sorprendió al descubrir que no lo hace SearchBuf primera búsqueda de la palabra y luego comprobar si hay delimitadores. En su lugar, pasa a través de los caracteres de la cadena de uno en uno en busca de un delimitador. Si lo encuentra, entonces compruebe la serie y otro delimitador. Si no lo encuentra, entonces busca otro delimitador. Por razones de eficacia, eso es muy inteligente!
Solución
Puede utilizar la función de SearchBuf con el [ soWholeWord] opción.
function SearchBuf(Buf: PAnsiChar; BufLen: Integer; SelStart: Integer; SelLength: Integer; SearchString: AnsiString; Options: TStringSearchOptions): PAnsiChar;
Vea este ejemplo
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;
Utilice esta manera
ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);
adiós.
Otros consejos
El hecho de que el editor de Delphi tiene una función de "coincidencia de palabras", eso no significa que la biblioteca Delphi ofrece él!
Por lo general, en la mayoría de idiomas el camino a seguir para esto es una expresión regular. Parece que son (todavía) no integrado en Delphi, ya que hay bibliotecas 3 ª parte que ofrecen la capacidad. El primer ejemplo que he encontrado es: http: //delphi.about .com / OD / toppicks / tp / delphi-regular-expressions.htm .
Por lo general, usted construye una expresión regular como algo
myRegex = '[' + Delim + ']+' + Word + '[' + Delim + ']+';
if regexSearch (Str, myRegex) then ...
querrá obtener detalles de la documentación de la biblioteca que se obtiene. Mi ejemplo no controla correctamente el caso de la palabra empezando por el principio o el final de Str en su extremo, o si todas Str.
Esta función no es exactamente lo que necesita, pero está bastante cerca:
Espero que sea ú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;
Si tiene la función, como a continuación
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;
y lo llaman así:
ExistWordInString('Go Delphi Go','Delphi',[soWholeWord,soDown]);
Es posible que no cayó ningún problema si se llama una vez. Pero si se llama a esto en un bucle (por ejemplo, 1000 veces o más) primero usando la función Pos (como abajo) sorprendentemente le dará la capacidad
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;