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

When using Fuse's useExtendedSearch, format-fuse can return overlapping matches #42

Open
fpintos opened this issue Feb 12, 2024 · 1 comment

Comments

@fpintos
Copy link

fpintos commented Feb 12, 2024

Performing a Fuse extended search for 'sao paulo' on an item that contains the text 'SAO PAULO' yields matches for [ [ 0, 2 ], [ 1, 2 ], [ 4, 8 ] ], and format-fuse returns them as SAO, AO an PAULO. Rendering those as shown in the readme causes the UI to show "SAOAO PAULO". Ideally, the resulting value would eliminate overlapping matches.

Example:

const Fuse = require('fuse.js');
const formatFuseJs = require('format-fuse.js').default;
const util = require('util');

const r = new Fuse([{ name: 'SAO PAULO' }], {
    keys: ['name'],
    includeMatches: true,
    includeScore: true,
    useExtendedSearch: true,
})
    .search('sao paulo')
    .map(s => ({ ...s, formatted: formatFuseJs([s])[0] }));

console.log(util.inspect(r, { showHidden: false, depth: null, colors: true }));

Actual:

[
  {
    item: { name: 'SAO PAULO' },
    refIndex: 0,
    matches: [
      {
        indices: [ [ 0, 2 ], [ 1, 2 ], [ 4, 8 ] ],
        value: 'SAO PAULO',
        key: 'name'
      }
    ],
    score: 0.06403390388180329,
    formatted: {
      name: [
        { text: 'SAO', matches: true },
        { text: 'AO', matches: true },
        { text: ' ', matches: false },
        { text: 'PAULO', matches: true }
      ]
    }
  }
]

Expected:

[
  {
    item: { name: 'SAO PAULO' },
    refIndex: 0,
    matches: [
      {
        indices: [ [ 0, 2 ], [ 1, 2 ], [ 4, 8 ] ],
        value: 'SAO PAULO',
        key: 'name'
      }
    ],
    score: 0.06403390388180329,
    formatted: {
      name: [
        { text: 'SAO', matches: true },
        { text: ' ', matches: false },
        { text: 'PAULO', matches: true }
      ]
    }
  }
]
@fpintos
Copy link
Author

fpintos commented Feb 12, 2024

Suggestion will be to process match indices with this function:

function getNonOverlappingSets(originalSet) {
    const sets = [...originalSet];
    // Sort the sets by the first element of each set
    sets.sort((a, b) => a[0] - b[0]);

    let result = [sets[0]];

    for (let i = 1; i < sets.length; i++) {
        // Get the last set in the result array
        let lastSet = result[result.length - 1];

        // If the current set does not overlap with the last set, add it to the result
        if (sets[i][0] > lastSet[1]) {
            result.push(sets[i]);
        }
    }

    return result;
}

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

No branches or pull requests

1 participant