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;

它的工作原理是函数传回相关的十进制数。结果 0 表示不匹配,介于 0 和 1 之间表示部分匹配,数字越大表示匹配越好,1 表示找到所有关键字,2 表示完全匹配。我还可以进行比较以仅包含具有一定百分比的结果,如下所示:

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

问题是我上面的方法只考虑了AND操作,这意味着它需要所有的关键字,并比较找到了多少关键字。但是,我还想同时实现ANDOR操作的组合,这是我的结构不支持的。所以我需要重新编写这个函数的核心来使这成为可能。

我想知道的不是如何写这个,而是德尔福中有什么东西可以让这成为可能吗?有人向我提到TDictionary哈希表是我需要的,但我不知道它与我正在做的事情有什么关系,因为我从未使用过它们。如果模式匹配已经存在于 Delphi XE2 中,我只是不想重新发明模式匹配的轮子。

4

1 回答 1

1

查找某些字符串模式的最简单方法是使用正则表达式引擎。您可以在 FPC 的网站上找到一些免费的单元和包。

http://wiki.freepascal.org/Regexpr

并阅读更多关于正则表达式的信息。

于 2013-02-01T11:03:55.433 回答