-
-
Notifications
You must be signed in to change notification settings - Fork 0
Commit
This commit does not belong to any branch on this repository, and may belong to a fork outside of the repository.
- Loading branch information
Showing
8 changed files
with
553 additions
and
0 deletions.
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -1,2 +1,49 @@ | ||
# Damerau-Levenshtein | ||
|
||
[![GitHub license](https://img.shields.io/github/license/el3um4s/Damerau-Levenshtein.svg)](https://github.com/el3um4s/Damerau-Levenshtein/blob/master/LICENSE) | ||
[![GitHub tag](https://img.shields.io/github/tag/el3um4s/Damerau-Levenshtein.svg)](https://GitHub.com/el3um4s/Damerau-Levenshtein/tags/) | ||
[![HitCount](http://hits.dwyl.com/el3um4s/Damerau-Levenshtein.svg)](http://hits.dwyl.com/el3um4s/Damerau-Levenshtein) | ||
|
||
Calculate the Damerau–Levenshtein distance between strings. | ||
|
||
### Usage | ||
|
||
Call to "distance" functions outputs an integer, the calculated Damerau-Levenshtein distance between 2 strings given as parameters. If the result is 0, strings are identical. The higher the result, the less similar strings are. | ||
|
||
```typescript | ||
import { distance} as damerau from "./mod.ts"; | ||
|
||
const firstString: string = "Hello"; | ||
const secondString: string = "Hello World"; | ||
|
||
const distance = damerau.distance(firstString, secondString); | ||
|
||
console.log( | ||
`Damerau–Levenshtein distance between "${firstString}" and "${secondString}" is: ${distance} `, | ||
); | ||
``` | ||
|
||
There are 1 demo available. The first demo queries Wikipedia and print the first result | ||
|
||
``` | ||
deno run .\demo.ts "Hello Wordl" "Hello world" | ||
``` | ||
|
||
You can run the demo directly from the repository with the commands: | ||
|
||
``` | ||
deno run https://raw.githubusercontent.com/el3um4s/Damerau-Levenshtein/master/demo.ts "Hello Wordl" "Hello world" | ||
``` | ||
|
||
I was inspirated by [fabvalaaah](https://github.com/fabvalaaah)'s repository [damerau-levenshtein-js](https://github.com/fabvalaaah/damerau-levenshtein-js) | ||
|
||
### API | ||
|
||
* **function compareDistance(a: StringWithDistance, b: StringWithDistance): number** : _Compare distance between 2 words (format like StringWithDistance)._ | ||
* **function distance(a: string, b: string)** : _Get the Damerau-Levenshtein distance between 2 strings_ | ||
* **function distanceDamerau(string: string, compared: string): StringWithDistance** : _Return an object with string, compared string and distance beetween_ | ||
* **function distanceList(target: string, list: Array<string>): Array<StringWithDistance>** : _Return an arry of StringWithDistance with the distance from the compared string_ | ||
* **function minDistance(string: string, list: Array<string>): number** : _Get the minimum Damerau-Levenshtein distance between a string and an array of strings_ | ||
* **function sortByMinDistance(list: Array<StringWithDistance>): Array<StringWithDistance>** : _Return an arry of StringWithDistance sorted by min distance_ | ||
* **function sortWordByMinDistance(target: string, list: Array<string>): Array<StringWithDistance>** : _Return an arry of StringWithDistance sorted by min distance_ | ||
* **interface StringWithDistance** : _Interface for string, compared string and distance beetween_ |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,12 @@ | ||
import { distance } from "./mod.ts"; | ||
|
||
const firstString: string = Deno.args.length > 0 ? Deno.args[0] : "Hello"; | ||
const secondString: string = Deno.args.length > 1 | ||
? Deno.args[1] | ||
: "Hello World"; | ||
|
||
const d = distance(firstString, secondString); | ||
|
||
console.log( | ||
`Damerau–Levenshtein distance between "${firstString}" and "${secondString}" is: ${d} `, | ||
); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,125 @@ | ||
/** Interface for string, compared string and distance beetween */ | ||
export interface StringWithDistance { | ||
string: string; | ||
compared: string; | ||
distance: number; | ||
} | ||
|
||
const initMatrix = (a: string, b: string): number[][] => { | ||
let d: number[][] = []; | ||
|
||
for (let i = 0; i <= a.length; i++) { | ||
d[i] = []; | ||
d[i][0] = i; | ||
} | ||
for (let j = 0; j <= b.length; j++) { | ||
d[0][j] = j; | ||
} | ||
|
||
return d; | ||
}; | ||
|
||
const damerau = ( | ||
i: number, | ||
j: number, | ||
a: string, | ||
b: string, | ||
d: number[][], | ||
cost: number, | ||
) => { | ||
if (i > 1 && j > 1 && a[i - 1] === b[j - 2] && a[i - 2] === b[j - 1]) { | ||
d[i][j] = Math.min.apply(null, [d[i][j], d[i - 2][j - 2] + cost]); | ||
} | ||
}; | ||
|
||
/** Get the Damerau-Levenshtein distance between 2 strings */ | ||
export function distance(a: string, b: string) { | ||
let d: number[][] = initMatrix(a, b); | ||
for (var i = 1; i <= a.length; i++) { | ||
let cost: number; | ||
for (let j = 1; j <= b.length; j++) { | ||
if (a.charAt(i - 1) === b.charAt(j - 1)) { | ||
cost = 0; | ||
} else { | ||
cost = 1; | ||
} | ||
|
||
d[i][j] = Math.min.apply(null, [ | ||
d[i - 1][j] + 1, | ||
d[i][j - 1] + 1, | ||
d[i - 1][j - 1] + cost, | ||
]); | ||
|
||
damerau(i, j, a, b, d, cost); | ||
} | ||
} | ||
return d[a.length][b.length]; | ||
}/** Return an arry of StringWithDistance with the distance from the compared string*/ | ||
|
||
export function distanceList( | ||
target: string, | ||
list: Array<string>, | ||
): Array<StringWithDistance> { | ||
return list.map((string) => { | ||
return distanceDamerau(target, string); | ||
}); | ||
}/** Return an object with string, compared string and distance beetween */ | ||
|
||
export function distanceDamerau( | ||
string: string, | ||
compared: string, | ||
): StringWithDistance { | ||
return { | ||
string: string, | ||
compared: compared, | ||
distance: distance(string, compared), | ||
}; | ||
} | ||
|
||
/** Compare distance between 2 words (format like StringWithDistance). */ | ||
export function compareDistance( | ||
a: StringWithDistance, | ||
b: StringWithDistance, | ||
): number { | ||
return a.distance > b.distance ? 1 : a.distance < b.distance ? -1 : 0; | ||
} | ||
|
||
/** Get the minimum Damerau-Levenshtein distance between a string and an array of strings*/ | ||
export function minDistance( | ||
string: string, | ||
list: Array<string>, | ||
): number { | ||
const arrayStrings: Array<StringWithDistance> = distanceList(string, list); | ||
return arrayStrings.length === 0 ? string.length : arrayStrings.reduce( | ||
(min, b) => Math.min(min, b.distance), | ||
arrayStrings[0].distance, | ||
); | ||
}/** Return an arry of StringWithDistance sorted by min distance */ | ||
|
||
export function sortByMinDistance( | ||
list: Array<StringWithDistance>, | ||
): Array<StringWithDistance> { | ||
return list.concat().sort(compareDistance); | ||
}/** Return an arry of StringWithDistance sorted by min distance */ | ||
|
||
export function sortWordByMinDistance( | ||
target: string, | ||
list: Array<string>, | ||
): Array<StringWithDistance> { | ||
const listWithDistance: Array<StringWithDistance> = distanceList( | ||
target, | ||
list, | ||
); | ||
return sortByMinDistance(listWithDistance); | ||
}// interface CompareStrings { | ||
// firstString: string; | ||
// secondString: string; | ||
// target: string; | ||
// } | ||
// | ||
// export function compareDistanceBetweenWords(obj: CompareStrings): number { | ||
// return compareDistance( | ||
// distanceDamerau(obj.firstString, obj.target), | ||
// distanceDamerau(obj.secondString, obj.target), | ||
// ); | ||
// } |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,50 @@ | ||
// | ||
// Copyright 2020 Samuele de Tomasi. All rights reserved. MIT license. | ||
|
||
import { | ||
assertStrictEquals, | ||
} from "https://deno.land/std/testing/asserts.ts"; | ||
|
||
import { | ||
compareDistanceBetweenWords, | ||
} from "../mod.ts"; | ||
|
||
Deno.test("compareDistanceBetweenWords (hello)(Heello)(hello)", (): void => { | ||
const a: string = "hello"; | ||
const b: string = "Heello"; | ||
const target: string = "hello"; | ||
const result = compareDistanceBetweenWords( | ||
{ firstString: a, secondString: b, target: target }, | ||
); | ||
assertStrictEquals(result, -1); | ||
}); | ||
|
||
Deno.test("compareDistanceBetweenWords (Milan)(Milano)(Milano)", (): void => { | ||
const a: string = "Milan"; | ||
const b: string = "Milano"; | ||
const target: string = "Milano"; | ||
const result = compareDistanceBetweenWords( | ||
{ firstString: a, secondString: b, target: target }, | ||
); | ||
assertStrictEquals(result, 1); | ||
}); | ||
|
||
Deno.test("compareDistanceBetweenWords (Milano)(Milano)(Milano)", (): void => { | ||
const a: string = "Milano"; | ||
const b: string = "Milano"; | ||
const target: string = "Milano"; | ||
const result = compareDistanceBetweenWords( | ||
{ firstString: a, secondString: b, target: target }, | ||
); | ||
assertStrictEquals(result, 0); | ||
}); | ||
|
||
Deno.test("compareDistanceBetweenWords (hello world)(HELLO WORLD)(HELLO world)", (): void => { | ||
const a: string = "hello world"; | ||
const b: string = "HELLO WORLD"; | ||
const target: string = "HELLO world"; | ||
const result = compareDistanceBetweenWords( | ||
{ firstString: a, secondString: b, target: target }, | ||
); | ||
assertStrictEquals(result, 0); | ||
}); |
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
@@ -0,0 +1,74 @@ | ||
// Copyright 2020 Samuele de Tomasi. All rights reserved. MIT license. | ||
|
||
import { | ||
assertStrictEquals, | ||
} from "https://deno.land/std/testing/asserts.ts"; | ||
|
||
import { | ||
compareDistance, | ||
StringWithDistance, | ||
} from "../mod.ts"; | ||
|
||
Deno.test("compareDistance a > b", (): void => { | ||
const a: StringWithDistance = { | ||
string: "hello", | ||
compared: "Hello", | ||
distance: 1, | ||
}; | ||
|
||
const b: StringWithDistance = { | ||
string: "hello", | ||
compared: "Heello", | ||
distance: 2, | ||
}; | ||
const result = compareDistance(a, b); | ||
assertStrictEquals(result, -1); | ||
}); | ||
|
||
Deno.test("compareDistance a < b", (): void => { | ||
const a: StringWithDistance = { | ||
string: "Milan", | ||
compared: "Milano", | ||
distance: 1, | ||
}; | ||
|
||
const b: StringWithDistance = { | ||
string: "Milano", | ||
compared: "Milano", | ||
distance: 0, | ||
}; | ||
const result = compareDistance(a, b); | ||
assertStrictEquals(result, 1); | ||
}); | ||
|
||
Deno.test("compareDistance a = b (Milano)(Milano)", (): void => { | ||
const a: StringWithDistance = { | ||
string: "Milano", | ||
compared: "Milano", | ||
distance: 0, | ||
}; | ||
|
||
const b: StringWithDistance = { | ||
string: "Milano", | ||
compared: "Milano", | ||
distance: 0, | ||
}; | ||
const result = compareDistance(a, b); | ||
assertStrictEquals(result, 0); | ||
}); | ||
|
||
Deno.test("compareDistance a = b (hello world)(HELLO WORLD)", (): void => { | ||
const a: StringWithDistance = { | ||
string: "hello world", | ||
compared: "HELLO world", | ||
distance: 5, | ||
}; | ||
|
||
const b: StringWithDistance = { | ||
string: "HELLO WORLD", | ||
compared: "HELLO world", | ||
distance: 5, | ||
}; | ||
const result = compareDistance(a, b); | ||
assertStrictEquals(result, 0); | ||
}); |
Oops, something went wrong.