/** Ngram fuzzy match algorithm * (simple and fast) */ const createNgram = (word, n) => { // Ngram creation if (word.length <3) return word; const vector = []; for (let i = 0; i < word.length-n+1; ++i) { vector.push(word.slice(i, i + n)); } return vector; }; /** check similarity between 2 words * based on Ngram matches of N = n letters * @param {string} a : first word * @param {string} b : second word * @param {int} n : Ngram base * @returns {float} : match percentage as a float in [0, 1] */ const similarity = (a, b, n) => { // Ngram match score if (a.length > 0 && b.length > 0) { const aNgram = createNgram(a, n); const bNgram = createNgram(b, n); let hits = 0; for (let x = 0; x < aNgram.length; ++x) { for (let y = 0; y < bNgram.length; ++y) { if (aNgram[x] === bNgram[y]) { hits += 1; } } } if (hits > 0) { const union = aNgram.length + bNgram.length; return (2.0 * hits) / union; } } return 0; }; /** is_exact_match * * check if a searching string -> query (string/latin in kb-format) * matches exactly an item of the array of synonyms -> chkArr (array of utf-8/strings) * * @param query (string): searching string; string/latin in kb-format * @param chkArr (array): array of synonyms; (array of utf-8/strings) * @return (boolean): true|false */ function exact( query, chkArr ) { found = false; chkArr.forEach( w => { if (w == query) found = true }); return found; } function partial( query, chkArr ) { found = false; chkArr.forEach( w => { if (w.includes(query)) found = true }); return found; } module.exports = { exact, partial, similarity, };