我当前项目的一部分是将搜索结果(仅限文件名)与搜索字符串(多个单词)进行比较。我有一个非常基本的机制,我现在用它来识别结果的相关性,所有这些都用一个函数处理。
搜索开始时,我将搜索字符串拆分为关键字的字符串列表...
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 操作,这意味着它需要所有关键字,并比较找到的关键字数量。但是,我想同时实现 AND 和 OR 操作的组合,我的结构不支持。所以我需要重新编写这个函数的内容才能实现这一点。
我想知道的不是如何写这个,但Delphi中是否有可能使这成为可能?有人向我提到TDictionary
作为哈希表是我需要的,但我不知道它与我正在做什么有关,因为我从未使用它们。如果它已经存在于Delphi XE2中,我只是不想重新发明模式匹配的轮子。
答案 0 :(得分:1)
找到一些字符串模式的最简单方法是使用正则表达式引擎。 您可以在FPC的网站上找到一些免费的单位和包裹。
http://wiki.freepascal.org/Regexpr
详细了解Regular Expression。