Add Levenshtein.

This commit is contained in:
Oleksii Trekhleb 2018-04-24 07:54:38 +03:00
parent 075fe39f5a
commit 8dd0c14af1
2 changed files with 66 additions and 0 deletions

View File

@ -0,0 +1,29 @@
import levenshteinDistance from '../levenshteinDistance';
describe('levenshteinDistance', () => {
it('should calculate edit distance between two strings', () => {
expect(levenshteinDistance('', '')).toBe(0);
expect(levenshteinDistance('a', '')).toBe(1);
expect(levenshteinDistance('', 'a')).toBe(1);
expect(levenshteinDistance('abc', '')).toBe(3);
expect(levenshteinDistance('', 'abc')).toBe(3);
// Should just add I to the beginning.
expect(levenshteinDistance('islander', 'slander')).toBe(1);
// Needs to substitute M by K, T by M and add an A to the end
expect(levenshteinDistance('mart', 'karma')).toBe(3);
// Substitute K by S, E by I and insert G at the end.
expect(levenshteinDistance('kitten', 'sitting')).toBe(3);
// Should add 4 letters FOOT at the beginning.
expect(levenshteinDistance('ball', 'football')).toBe(4);
// Should delete 4 letters FOOT at the beginning.
expect(levenshteinDistance('football', 'foot')).toBe(4);
// Needs to substitute the first 5 chars: INTEN by EXECU
expect(levenshteinDistance('intention', 'execution')).toBe(5);
});
});

View File

@ -0,0 +1,37 @@
/**
* @param {string} a
* @param {string} b
* @return {number}
*/
export default function levenshteinDistance(a, b) {
// Create empty edit distance matrix for all possible modifications of
// substrings of a to substrings of b.
const distanceMatrix = Array(b.length + 1).fill(null).map(() => Array(a.length + 1).fill(null));
// Fill the first raw of the matrix.
// If this is first row then we're transforming empty string to a.
// In this case the number of transformations equals to size of a substring.
for (let i = 0; i <= a.length; i += 1) {
distanceMatrix[0][i] = i;
}
// Fill the first column of the matrix.
// If this is first column then we're transforming empty string to b.
// In this case the number of transformations equals to size of b substring.
for (let j = 0; j <= b.length; j += 1) {
distanceMatrix[j][0] = j;
}
for (let j = 1; j <= b.length; j += 1) {
for (let i = 1; i <= a.length; i += 1) {
const indicator = a[i - 1] === b[j - 1] ? 0 : 1;
distanceMatrix[j][i] = Math.min(
distanceMatrix[j][i - 1] + 1, // deletion
distanceMatrix[j - 1][i] + 1, // insertion
distanceMatrix[j - 1][i - 1] + indicator, // substitution
);
}
}
return distanceMatrix[b.length][a.length];
}