Delphiで効率的な単語全体の検索機能はありますか?
質問
、後のDelphi 2009または(ユニコード)では、任意の組み込み関数またはあなたが言葉を定義する区切り文字を提供し、合理的、効率的な単語全体の検索を行いますどこかに書かれた小さなルーチンは例えば、あります。
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 }
私は唯一の「言葉」は文字列である場合、これは真または偽の値を返す必要があります。
標準のダイアログがそれのオプションの1つとして「単語単位のみを」持って検索するので、このどこかのために何が存在する必要があります。
はどのようにこの通常(または最高)実装?
<時間>結論ます:
RRUZの答えは完璧でした。 SearchBufルーチンは、私は必要なものだけでした。私も、StrUtilsルーチンに入るコードを抽出し、私の要件に合うようにそれを変更することができます。
私はSearchBufは、単語の最初の検索がいないことが判明して、区切り文字をチェックして驚きました。その代わりに、区切り記号を探して一度に文字列1の文字を通過します。それが1つを見つけた場合、それは文字列と、別の区切り文字をチェックします。それが見つからない場合は、その後、別の区切り文字を探します。効率のために、それは非常にスマートです!
解決
あなたは[と 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のライブラリがそれを提供していますという意味ではありません!
一般的に、ほとんどの言語で、このために移動するための方法は、正規表現です。機能を提供するサードパーティのライブラリがあるので、彼らは(まだ)デルファイに組み込まれていないようです。私が最初に見つかった例は次のとおりです。のhttp://delphi.about .COM / OD / toppicks / TP /デルファイ-正規expressions.htm でます。
一般的には、
のような正規表現の何かを構築したいですmyRegex = '[' + Delim + ']+' + Word + '[' + Delim + ']+';
if regexSearch (Str, myRegex) then ...
あなたが取得するライブラリのドキュメントから詳細を取得したいと思います。私の例では、正しく筋力の先頭から始まるか、その終わりで終了、または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倍以上)をループ内でこれを呼び出す場合でも、驚くほどあなたに余分なパフォーマンスが得られます。
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;