@technobuddha/library
Version:
A large library of useful functions
82 lines (72 loc) • 2.29 kB
text/typescript
import { create2dArray } from './create2d-array.ts';
/**
* Options for the {@link levenshteinDistance} function
* @group String
* @category Fuzzy Match
*/
export type LevenshteinDistanceOptions = {
/** The comparison will ignore case */
caseInsensitive?: boolean;
};
/**
* Compute the levenshtein distance between two strings (similarity)
* @param input - The string
* @param comparedTo - The string to compare to
* @param options - see {@link LevenshteinDistanceOptions}
* @defaultValue caseInsensitive true
* @returns the levenshteinDistance between the two strings (0 for no similarity through 1 for equal)
* @group String
* @category Fuzzy Match
*/
export function levenshteinDistance(
input: string,
comparedTo: string,
{ caseInsensitive = true }: LevenshteinDistanceOptions = {},
): number {
let argInput = input;
let argComparedTo = comparedTo;
if (argInput.length === 0 || comparedTo.length === 0) {
return Math.max(argInput.length, comparedTo.length);
}
if (caseInsensitive) {
argInput = argInput.toLocaleLowerCase();
argComparedTo = argComparedTo.toLocaleLowerCase();
}
const inputLen = argInput.length;
const comparedToLen = argComparedTo.length;
const matrix = create2dArray(inputLen, comparedToLen, 0);
//initialize
for (let i = 0; i < inputLen; ++i) {
matrix[i][0] = i;
}
for (let i = 0; i < comparedToLen; ++i) {
matrix[0][i] = i;
}
//analyze
for (let i = 1; i < inputLen; ++i) {
const si = argInput.charAt(i - 1);
for (let j = 1; j < comparedToLen; ++j) {
const tj = argComparedTo.charAt(j - 1);
const cost = si === tj ? 0 : 1;
const above = matrix[i - 1][j];
const left = matrix[i][j - 1];
const diag = matrix[i - 1][j - 1];
let cell = Math.min(Math.min(above + 1, left + 1), diag + cost);
//transposition
if (i > 1 && j > 1) {
let trans = matrix[i - 2][j - 2] + 1;
if (argInput.charAt(i - 2) !== argComparedTo.charAt(j - 1)) {
trans++;
}
if (argInput.charAt(i - 1) !== argComparedTo.charAt(j - 2)) {
trans++;
}
if (cell > trans) {
cell = trans;
}
}
matrix[i][j] = cell;
}
}
return matrix[inputLen - 1][comparedToLen - 1];
}