109 lines
2.3 KiB
TypeScript
109 lines
2.3 KiB
TypeScript
![]() |
|
||
|
export class LevenshteinFuzzyMatch
|
||
|
{
|
||
|
lowestDistance:number;
|
||
|
index:number;
|
||
|
}
|
||
|
|
||
|
export class LevenshteinDistance
|
||
|
{
|
||
|
protected static getMatrix( aLength:number, bLength:number )
|
||
|
{
|
||
|
let matrix:number[][] = [];
|
||
|
|
||
|
for ( let i = 0; i < aLength + 1; i++ )
|
||
|
{
|
||
|
let bArray = [];
|
||
|
|
||
|
for ( let j = 0; j < bLength + 1; j++ )
|
||
|
{
|
||
|
bArray.push( 0 );
|
||
|
}
|
||
|
|
||
|
matrix.push( bArray );
|
||
|
}
|
||
|
|
||
|
for ( let i = 0; i <= aLength; i++ )
|
||
|
{
|
||
|
matrix[ i ][ 0 ] = i;
|
||
|
}
|
||
|
|
||
|
for ( let j = 0; j <= bLength; j++ )
|
||
|
{
|
||
|
matrix[ 0 ][ j ] = j;
|
||
|
}
|
||
|
|
||
|
return matrix;
|
||
|
}
|
||
|
|
||
|
static computeFuzzyMatch( value:string, matcher:string )
|
||
|
{
|
||
|
let result = new LevenshteinFuzzyMatch();
|
||
|
|
||
|
if ( matcher.length >= value.length )
|
||
|
{
|
||
|
result.index = 0;
|
||
|
result.lowestDistance = LevenshteinDistance.compute( value, matcher );
|
||
|
|
||
|
}
|
||
|
else
|
||
|
{
|
||
|
let offsets = value.length - matcher.length;
|
||
|
|
||
|
for ( let i = 0; i < offsets; i++ )
|
||
|
{
|
||
|
let subValue = value.substring( i, i + matcher.length );
|
||
|
let distance = LevenshteinDistance.compute( subValue, matcher );
|
||
|
|
||
|
if ( i === 0 )
|
||
|
{
|
||
|
result.index = 0;
|
||
|
result.lowestDistance = distance;
|
||
|
continue;
|
||
|
}
|
||
|
|
||
|
if ( distance < result.lowestDistance )
|
||
|
{
|
||
|
result.index = i;
|
||
|
result.lowestDistance = distance;
|
||
|
}
|
||
|
|
||
|
}
|
||
|
}
|
||
|
|
||
|
|
||
|
return result;
|
||
|
}
|
||
|
|
||
|
|
||
|
static compute( a:string, b:string ):number
|
||
|
{
|
||
|
let aLength = a.length;
|
||
|
let bLength = b.length;
|
||
|
|
||
|
if ( aLength == 0 ) { return bLength; }
|
||
|
if ( bLength == 0 ) { return aLength; }
|
||
|
|
||
|
let evaluationMatrix = LevenshteinDistance.getMatrix( aLength, bLength );
|
||
|
|
||
|
for ( let i = 1; i <= aLength; i++ )
|
||
|
{
|
||
|
for ( let j = 1; j <= bLength; j++ )
|
||
|
{
|
||
|
let isSame = b[ j - 1 ] === a[ i - 1 ];
|
||
|
|
||
|
let isDifferentCost = isSame ? 0 : 1;
|
||
|
|
||
|
let insertionCost = evaluationMatrix[ i - 1][ j ] + 1;
|
||
|
let deletionCost = evaluationMatrix[ i ][ j - 1 ] + 1;
|
||
|
let substitutionCost = evaluationMatrix[ i - 1][ j - 1 ] + isDifferentCost;
|
||
|
|
||
|
evaluationMatrix[ i ][ j ] = Math.min( insertionCost, deletionCost, substitutionCost );
|
||
|
}
|
||
|
}
|
||
|
|
||
|
return evaluationMatrix[ aLength][ bLength ];
|
||
|
}
|
||
|
}
|
||
|
|