2009-11-05 4 views
5

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:¿Existe una función eficiente de búsqueda de palabras completas en Delphi?

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 } 

Sólo necesito que esto devuelve un valor verdadero o falso si la "Palabra" se encuentra en la cadena.

Debe haber algo para esto en alguna parte, porque el Diálogo de Buscar estándar tiene "Coincidir palabra completa solamente" como una de sus opciones.

¿Cómo se implementa normalmente (o mejor)?


Conclusión:

respuesta de RRUZ era perfecto. La rutina SearchBuf era justo lo que necesitaba. Incluso puedo acceder a la rutina de StrUtils, extraer el código y modificarlo para adaptarlo a mis requisitos.

Me sorprendió encontrar que SearchBuf no busca primero la palabra y luego busca los delimitadores. En su lugar, recorre los caracteres de la cadena uno a la vez buscando un delimitador. Si encuentra uno, entonces busca la cadena y otro delimitador. Si no lo encuentra, busca otro delimitador. ¡Por la eficiencia, eso es muy inteligente!

Respuesta

13

Puede usar la función SearchBuf con la opción [soWholeWord].

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

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

usarlo de esta manera

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

adiós.

+1

¡Bonito! Ahora publicaste tu solución en tu propio blog en: http://theroadtodelphi.wordpress.com/2009/11/05 y la encontré mientras investigaba más. Gracias por la información adicional que proporciona allí. – lkessler

+0

'ExistWordInString ('Delphi', 'Delphi' [soWholeWord, soDown]);' falla. Consulte [Resultado inesperado de SearchBuf soWholeWord] (http://stackoverflow.com/q/25877986/576719). –

2

El hecho de que el editor de Delphi tenga una función de "coincidencia de palabras", ¡eso no significa que la biblioteca Delphi lo ofrezca!

Normalmente, en la mayoría de los idiomas, el camino a seguir para esto es una expresión regular. Parece que (todavía) no están integrados en Delphi, ya que hay bibliotecas de terceros que ofrecen esta capacidad. El primer ejemplo que encontré 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 ... 

Usted querrá obtener detalles de la documentación de la biblioteca que se obtiene. Mi ejemplo no maneja correctamente el caso de la palabra que comienza al principio de Str o termina al final, o es todo de Str.

0

esta función no es exactamente lo que necesita, pero es bastante estrecha:

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

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 llamada es así:

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

Es posible que no se le ocurra ningún problema si lo llama una vez. Pero si llama esto en un bucle (por ejemplo, 1000 veces o más), primero usar la función Pos (como a continuación) le dará un desempeño 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; 
Cuestiones relacionadas