partialRatio function
Calculates a partial ratio between two strings Matches the behavior of RapidFuzz's partial_ratio implementation
Implementation
double partialRatio(String s1, String s2, {double scoreCutoff = 0.0}) {
final len1 = s1.length;
final len2 = s2.length;
// RapidFuzz swaps the strings to ensure s1 is always the shorter one
if (len1 > len2) {
return partialRatio(s2, s1, scoreCutoff: scoreCutoff);
}
// Handle cutoff > 100
if (scoreCutoff > 100) return 0.0;
// Handle empty strings - RapidFuzz returns 100 if both empty, 0 otherwise
if (len1 == 0 || len2 == 0) {
return (len1 == len2) ? 100.0 : 0.0;
}
// Perfect match
if (s1 == s2) return 100.0;
// Find best substring match
var bestScore = 0.0;
// When len2 > len1, try to find the best matching substring
if (len2 > len1) {
// Try all possible substrings of s2 with length len1
for (var i = 0; i <= len2 - len1; i++) {
final subStr = s2.substring(i, i + len1);
final currentScore = ratio(s1, subStr, scoreCutoff: bestScore);
bestScore = max(bestScore, currentScore);
if (bestScore == 100.0) return 100.0;
}
}
// For strings of same length, check ratio in both directions
if (s1.length == s2.length && bestScore != 100.0) {
final reversedScore = ratio(s2, s1, scoreCutoff: bestScore);
bestScore = max(bestScore, reversedScore);
}
// Also check beginning and end of string s2 for partial matches
// Check partial matches with the beginning of s2 (increasing size)
for (var i = 1; i < len1; i++) {
final s1Substr = s1.substring(0, i);
final s2Substr = s2.substring(0, i);
if (s1.codeUnitAt(i - 1) != s2.codeUnitAt(i - 1)) continue;
final currentScore = ratio(s1Substr, s2Substr, scoreCutoff: bestScore);
if (currentScore > bestScore) {
bestScore = currentScore;
if (bestScore == 100.0) return 100.0;
}
}
// Check partial matches with the end of s2 (decreasing size)
for (var i = len2 - 1; i >= len2 - len1; i--) {
final s1Substr = s1.substring(len1 - (len2 - i));
final s2Substr = s2.substring(i);
if (s1.codeUnitAt(0) != s2.codeUnitAt(i)) continue;
final currentScore = ratio(s1Substr, s2Substr, scoreCutoff: bestScore);
if (currentScore > bestScore) {
bestScore = currentScore;
if (bestScore == 100.0) return 100.0;
}
}
return bestScore;
}