49 lines
1.2 KiB
TypeScript

const { min } = Math;
// a minimal leven distance implementation
// balanced maintenability with code size
// It is not blazingly fast but should be okay for Babel user case
// where it will be run for at most tens of time on strings
// that have less than 20 ASCII characters
// https://rosettacode.org/wiki/Levenshtein_distance#ES5
function levenshtein(a: string, b: string): number {
let t = [],
u = [],
i,
j;
const m = a.length,
n = b.length;
if (!m) {
return n;
}
if (!n) {
return m;
}
for (j = 0; j <= n; j++) {
t[j] = j;
}
for (i = 1; i <= m; i++) {
for (u = [i], j = 1; j <= n; j++) {
u[j] =
a[i - 1] === b[j - 1] ? t[j - 1] : min(t[j - 1], t[j], u[j - 1]) + 1;
}
t = u;
}
return u[n];
}
/**
* Given a string `str` and an array of candidates `arr`,
* return the first of elements in candidates that has minimal
* Levenshtein distance with `str`.
* @export
* @param {string} str
* @param {string[]} arr
* @returns {string}
*/
export function findSuggestion(str: string, arr: readonly string[]): string {
const distances = arr.map<number>(el => levenshtein(el, str));
return arr[distances.indexOf(min(...distances))];
}