From 1b5c0082efb2224be80f3b8128a1c17a1f1bac99 Mon Sep 17 00:00:00 2001 From: Hans <hans@hansl.ca> Date: Tue, 4 Sep 2018 14:18:14 -0700 Subject: [PATCH] feat(@angular-devkit/core): add levenshtein distance utility --- .../angular_devkit/core/src/utils/strings.ts | 49 +++++++++++++++++++ 1 file changed, 49 insertions(+) diff --git a/packages/angular_devkit/core/src/utils/strings.ts b/packages/angular_devkit/core/src/utils/strings.ts index 4743e9cb65..ff3c0ce7ce 100644 --- a/packages/angular_devkit/core/src/utils/strings.ts +++ b/packages/angular_devkit/core/src/utils/strings.ts @@ -127,3 +127,52 @@ export function underscore(str: string): string { export function capitalize(str: string): string { return str.charAt(0).toUpperCase() + str.substr(1); } + +/** + * Calculate the levenshtein distance of two strings. + * See https://en.wikipedia.org/wiki/Levenshtein_distance. + * Based off https://gist.github.com/andrei-m/982927 (for using the faster dynamic programming + * version). + * + * @param a String a. + * @param b String b. + * @returns A number that represents the distance between the two strings. The greater the number + * the more distant the strings are from each others. + */ +export function levenshtein(a: string, b: string): number { + if (a.length == 0) { + return b.length; + } + if (b.length == 0) { + return a.length; + } + + const matrix = []; + + // increment along the first column of each row + for (let i = 0; i <= b.length; i++) { + matrix[i] = [i]; + } + + // increment each column in the first row + for (let j = 0; j <= a.length; j++) { + matrix[0][j] = j; + } + + // Fill in the rest of the matrix + for (let i = 1; i <= b.length; i++) { + for (let j = 1; j <= a.length; j++) { + if (b.charAt(i - 1) == a.charAt(j - 1)) { + matrix[i][j] = matrix[i - 1][j - 1]; + } else { + matrix[i][j] = Math.min( + matrix[i - 1][j - 1] + 1, // substitution + matrix[i][j - 1] + 1, // insertion + matrix[i - 1][j] + 1, // deletion + ); + } + } + } + + return matrix[b.length][a.length]; +}