Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Fuzzy header search #380

Open
wants to merge 10 commits into
base: main
Choose a base branch
from
Open

Conversation

PratyushChauhan
Copy link

PR Description

Previously we were only checking if a pattern is present in a header string. As a result you would not get suggestions if you made a typo.
BEFORE:
320200891-35e13df0-5a8a-49bd-adf9-a96b5e22d569

This PR attempts to fix this issue using Fuzzy package.

AFTER:
320200720-079a90ca-80e6-41fe-ad90-6e37702410bb

Related Issues

Checklist

  • I have gone through the contributing guide
  • I have updated my branch and synced it with project main branch before making this PR
  • I have run the tests (flutter test) and all tests are passing

Added/updated tests?

All previous tests except one have been added for the new function.

  • Yes
  • No, and this is why: please replace this line with details on why tests have not been included

@animator
Copy link
Member

animator commented Apr 6, 2024

It should show recommendation if there is a typo but if an exact substring match exists, it should show only them.

@PratyushChauhan
Copy link
Author

PratyushChauhan commented Apr 7, 2024

It should show recommendation if there is a typo but if an exact substring match exists, it should show only them.

@animator I have a suggestion to implement this.

in getFuzzyHeaderSuggestions():

List<String> getFuzzyHeaderSuggestions(String pattern) {
  final keys = headers.keys.toList();
  final fuse = Fuzzy(keys,
      options: FuzzyOptions(
        distance: 10,
        tokenize: true,
        matchAllTokens: true,
        tokenSeparator: "-",
        threshold: 0.2,
        shouldSort: true,
        minMatchCharLength: 1,
      ));
  final results = fuse.search(pattern);
  final List<String> suggestions =
      results.map((result) => result.item as String).toList();
  return suggestions;
}

when we obtain suggestions we can then iteratively sort them into 2 lists, "predictions" and "recommendations" {in case there is a typo}.

Example: every suggestion that exactly contains(pattern) will be a "prediction", else it will go to "recommendations".
Then if predictions.length == 0 in which case the user made a typo, we will display the fuzzy "recommendations" list otherwise we will only display "predictions" that will contain the pattern substring.

Let me know if this is desirable.

@PratyushChauhan
Copy link
Author

Doing this also passes the one test case I had to edit. This should do better than the previous approach.

@PratyushChauhan
Copy link
Author

Passes all test cases and does not show approximate suggestions if no typo exists. If typo exists then it shows fuzzy suggestions.

@ashitaprasad
Copy link
Member

@PratyushChauhan For the case, when the user just types a the result should include headers beginning with a followed by other headers. This is not happening currently.

Screenshot 2024-04-11 at 8 05 32 AM

@PratyushChauhan
Copy link
Author

@ashitaprasad worked on your suggestion, now the first character match is given preference in predictions.

image

@animator
Copy link
Member

@PratyushChauhan Why is Accept lower than Accept-Charset in your implementation?

@PratyushChauhan
Copy link
Author

@animator this most likely happens when we re-order the predictions {in case of typo} to include first character matching strings near the top.

// sort the predictions based on first character match
  for (int i = 0; i < predictions.length; i++) {
    if (predictions[i][0].toLowerCase() == pattern[0].toLowerCase()) {
      final String temp = predictions.removeAt(i);
      predictions.insert(0, temp); //push to front
    }
  }

In case of a typo each string that has a matching first character is pushed to position 0. Hence the order given by the fuzzy finder is reversed which makes Accept have a lower ranking than Accept-Charset.

A way to fix this would be to introduce a currentIndex variable to keep track of which index we need to push to. This will preserve the order given by the fuzzy finder package.

Fix:

  int currentIndex = 0;
  // sort the predictions based on first character match
  for (int i = 0; i < predictions.length; i++) {
    if (predictions[i][0].toLowerCase() == pattern[0].toLowerCase()) {
      final String temp = predictions.removeAt(i);
      predictions.insert(currentIndex, temp); //push to front
      currentIndex++;
    }
  }

image

@PratyushChauhan
Copy link
Author

@animator @ashitaprasad is this implementation fine?

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

Implement fuzzy string matching to get header suggestions
3 participants