[PTRun]Improve fuzzy search for queries (#20064)

* Update StringMatcher.cs

* Update tests

* Remove comment
This commit is contained in:
ivanstosic-janea
2022-09-27 19:17:20 +02:00
committed by GitHub
parent 665851300d
commit bed18a418c
2 changed files with 30 additions and 4 deletions

View File

@@ -56,6 +56,27 @@ namespace Wox.Infrastructure
/// 7. Consider success and move onto scoring if every char or substring without whitespaces matched
/// </summary>
public MatchResult FuzzyMatch(string query, string stringToCompare, MatchOption opt)
{
if (string.IsNullOrEmpty(stringToCompare))
{
return new MatchResult(false, UserSettingSearchPrecision);
}
var bestResult = new MatchResult(false, UserSettingSearchPrecision);
for (int startIndex = 0; startIndex < stringToCompare.Length; startIndex++)
{
MatchResult result = FuzzyMatch(query, stringToCompare, opt, startIndex);
if (result.Success && (!bestResult.Success || result.Score > bestResult.Score))
{
bestResult = result;
}
}
return bestResult;
}
private MatchResult FuzzyMatch(string query, string stringToCompare, MatchOption opt, int startIndex)
{
if (string.IsNullOrEmpty(stringToCompare) || string.IsNullOrEmpty(query))
{
@@ -88,7 +109,7 @@ namespace Wox.Infrastructure
var indexList = new List<int>();
List<int> spaceIndices = new List<int>();
for (var compareStringIndex = 0; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
for (var compareStringIndex = startIndex; compareStringIndex < fullStringToCompareWithoutCase.Length; compareStringIndex++)
{
// To maintain a list of indices which correspond to spaces in the string to compare
// To populate the list only for the first query substring
@@ -239,7 +260,12 @@ namespace Wox.Infrastructure
// A match found near the beginning of a string is scored more than a match found near the end
// A match is scored more if the characters in the patterns are closer to each other,
// while the score is lower if they are more spread out
var score = 100 * (query.Length + 1) / ((1 + firstIndex) + (matchLen + 1));
// The length of the match is assigned a larger weight factor.
// I.e. the length is more important than where in the string a match is found.
const int matchLenWeightFactor = 2;
var score = 100 * (query.Length + 1) * matchLenWeightFactor / ((1 + firstIndex) + (matchLenWeightFactor * (matchLen + 1)));
// A match with less characters assigning more weights
if (stringToCompare.Length - query.Length < 5)

View File

@@ -156,7 +156,7 @@ namespace Wox.Test
[DataRow("goo", "Google Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
[DataRow("chr", "Google Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
[DataRow("chr", "Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
[DataRow("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, false)]
[DataRow("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Regular, true)]
[DataRow("chr", "Help cure hope raise on mind entity Chrome", StringMatcher.SearchPrecisionScore.Low, true)]
[DataRow("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.Regular, false)]
[DataRow("chr", "Candy Crush Saga from King", StringMatcher.SearchPrecisionScore.None, true)]
@@ -203,7 +203,7 @@ namespace Wox.Test
[DataRow("mic", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, true)]
[DataRow("chr", "Shutdown", StringMatcher.SearchPrecisionScore.Regular, false)]
[DataRow("mssms", MicrosoftSqlServerManagementStudio, StringMatcher.SearchPrecisionScore.Regular, false)]
[DataRow("chr", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, false)]
[DataRow("chr", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, true)]
[DataRow("ch r", "Change settings for text-to-speech and for speech recognition (if installed).", StringMatcher.SearchPrecisionScore.Regular, true)]
[DataRow("a test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]
[DataRow("test", "This is a test", StringMatcher.SearchPrecisionScore.Regular, true)]