jamoLevenshteinDistance static method
double
jamoLevenshteinDistance(
- String s1,
- String s2, {
- PhonemeCost? phonemeCost,
- bool debug = false,
Computes the Levenshtein distance between two Korean strings based on decomposed phonemes.
Parameters:
s1
: The first Korean string.s2
: The second Korean string.phonemeCost
: Customized weights for different phonemes.debug
: Whether to print debugging information.
Returns the Levenshtein distance between the two strings.
Implementation
static double jamoLevenshteinDistance(String s1, String s2,
{PhonemeCost? phonemeCost, bool debug = false}) {
if (s1.length < s2.length) {
return jamoLevenshteinDistance(s2, s1, debug: debug);
}
if (s2.isEmpty) return s1.length.toDouble();
double substitutionCost(String c1, String c2) {
if (c1 == c2) return 0;
final decomposedC1 = c1.decompose();
final decomposedC2 = c2.decompose();
if (decomposedC1 == null || decomposedC2 == null) {
throw const NonKoreanContainsException();
}
return _levenshtein(
decomposedC1.join(),
decomposedC2.join(),
phonemeCost: phonemeCost,
) /
3;
}
List<double> previousRow =
List<double>.generate(s2.length + 1, (int index) => index.toDouble());
for (int i = 0; i < s1.length; i++) {
List<double> currentRow = [i + _defaultDistanceCost];
for (int j = 0; j < s2.length; j++) {
double insertions = previousRow[j + 1] + _defaultDistanceCost;
double deletions = currentRow[j] + _defaultDistanceCost;
double substitutions = previousRow[j] + substitutionCost(s1[i], s2[j]);
currentRow.add([insertions, deletions, substitutions]
.reduce((a, b) => a < b ? a : b));
}
if (debug) {
print(currentRow
.sublist(1)
.map((double v) => v.toStringAsFixed(3))
.toList());
}
previousRow = currentRow;
}
return previousRow.last;
}