/** 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; }; /** similarity * rates similarity between 2 words * based on Ngram matches of N = n letters; * implements a 2-dim check (all a-Ngrams vs all all b-Ngrams) * * @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; }; /** resemblance * is an alternative similarity rating; * implements an 1-dim Ngram similarity check * and it's much faster than similarity() */ const resemblance = (a, b, n) => { if (a.length > n && b.length >= a.length) { const aNgram = createNgram(a, n); let hits = 0; for (let i = 0; i < aNgram.length; ++i) { if (b.includes(aNgram[i])) { hits++; } } if (hits > 0) { // rate resemblance based on hits and length-similarity return (hits / aNgram.length) * (a.length / b.length); } } 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, resemblance }