UNPKG

@technobuddha/library

Version:
82 lines (72 loc) 2.29 kB
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]; }