1

私の現在のプロジェクトの一部は、検索結果 (ファイル名のみ) と検索文字列 (複数の単語) を比較することです。私は現在、結果の関連性を特定するために使用している非常に基本的なメカニズムを持っています。これらはすべて 1 つの関数で処理されます。

検索が始まると、検索文字列をキーワードの文字列リストに分割します...

procedure TSearcherThread.ParseKeywords;
var
  S, T: String;
  P: Integer;
begin
  //Clear current list of keywords
  FKeywords.Clear;
  S:= LowerCase(Trim(FSearchString));
  //Remove all excess spaces
  while Pos('  ', S) > 1 do
    S:= StringReplace(S, '  ', ' ', [rfReplaceAll]);
  if Copy(S, Length(S)-1, 1) <> ';' then
    S:= S + ';';
  //Parse out keywords
  while Length(S) > 0 do begin
    P:= Pos(';', S);
    T:= Copy(S, 1, P-1);
    Delete(S, 1, P);
    FKeywords.Append(T);
  end;
end;

検索するファイルのマスター リストを反復処理するときは、各ファイル名をこの関数に渡します...

function TSearcherThread.MatchKeywords(const Filename: String): Single;
var
  S: String; //Temp keywords
  FN: String; //Filename
  X: Integer; //Iterator
  C: Integer; //Match counter
begin
  Result:= 0; //Default no match
  S:= Trim(LowerCase(FSearchString)); //Lowercase Keywords, trim outside spaces
  FN:= LowerCase(ExtractFileName(Filename)); //Get lowercase filename
  Delete(FN, Pos('.', FN), MAXINT); //Strip off extension leaving only the name

  //Check if exact match
  if FN = S then Result:= 2;

  //If nothing matches yet, then look for individual keywords...
  if Result < 2 then begin
    C:= 0;
    if FKeywords.Count > 0 then begin
      //Iterate through keywords
      for X := 0 to FKeywords.Count - 1 do begin
        //If keyword is found in filename
        if Pos(FKeywords[X], FN) > 0 then begin
          Inc(C);
        end;
      end;
      //Return how often keywords showed up
      Result:= C / FKeywords.Count;
    end;
  end;
end;

これがどのように機能するかは、関数が関連性の 10 進数を返すことです。結果が 0 の場合は一致しないことを意味し、0 ~ 1 の場合は部分一致を意味し、数字が大きいほど一致度が高く、1 はすべてのキーワードが見つかったことを意味し、2 は完全一致であることを意味します。次のように、特定のパーセンテージを持つ結果のみを含めるように比較することもできます。

M:= MatchKeywords(Filename);
if M >= 0.2 then AddResult(Filename);

問題は、上記の方法がAND演算のみを考慮していることです。つまり、すべてのキーワードを想定し、見つかったキーワードの数を比較しています。ただし、私の構造ではサポートされていないAND演算とOR演算の組み合わせも実装したいと考えています。したがって、これを可能にするには、この関数の中身を書き直す必要があります。

私が知りたいのは、これを書く方法ではありませんが、Delphi でこれを可能にするものはありますか? ハッシュテーブルが必要だと誰かが私に言いTDictionaryましたが、私はそれらを使用したことがないので、それが私がしていることとどのように関係しているかわかりません。パターン マッチングのホイールが Delphi XE2 に既に存在する場合、再発明したくありません。

4

1 に答える 1

1

文字列パターンを見つける最も簡単な方法は、正規表現エンジンを使用することです。FPC の Web サイトで、いくつかの無料のユニットとパッケージを見つけることができます。

http://wiki.freepascal.org/Regexpr

そして正規表現についてもっと読んでください。

于 2013-02-01T11:03:55.433 に答える