pretty good

This commit is contained in:
Fabian Freund
2025-02-07 20:45:47 +01:00
parent 025ecaf2e3
commit a12ef8244f
68 changed files with 2359 additions and 1015 deletions
@@ -24,7 +24,83 @@ class TokenizedFilter<T> {
);
}
factory TokenizedFilter({
static double _calculateScore(
List<String> queryTokens,
List<String> targetTokens,
) {
if (queryTokens.isEmpty || targetTokens.isEmpty) return 0.0;
var score = 0.0;
var exactMatches = 0;
var partialMatches = 0;
for (final queryToken in queryTokens) {
var hasMatch = false;
for (int i = 0; i < targetTokens.length; i++) {
final targetToken = targetTokens[i];
if (targetToken == queryToken) {
// Exact match gets 1.0 points
score += 1.0;
exactMatches++;
hasMatch = true;
break;
} else if (targetToken.contains(queryToken)) {
// Partial match gets points based on match length ratio
final ratio = queryToken.length / targetToken.length;
score += ratio * 0.8; // Partial matches worth 80% of exact matches
partialMatches++;
hasMatch = true;
break;
}
}
if (!hasMatch) {
score -= 0.2; // Penalty for unmatched query tokens
}
}
// Normalize score based on number of query tokens and matches
final matchRatio =
(exactMatches + partialMatches * 0.8) / queryTokens.length;
score = score / queryTokens.length; // Normalize by query length
// Apply match ratio as a multiplier
score *= matchRatio;
// Ensure score is between 0 and 1
return score.clamp(0.0, 1.0);
}
factory TokenizedFilter.sort({
required Iterable<T> items,
required ToString<T> toString,
required String query,
}) {
final queryTokens = _tokenize(query);
final scoredItems = items.map((item) {
final itemString = toString(item);
if (itemString == null || itemString.isEmpty) {
return (item, 0.0);
}
final itemTokens = _tokenize(itemString);
final score = _calculateScore(queryTokens, itemTokens);
return (item, score);
}).toList();
// Sort by score in descending order
scoredItems.sort((a, b) => b.$2.compareTo(a.$2));
// Extract just the items in sorted order
final sorted = scoredItems.map((e) => e.$1).toList();
return TokenizedFilter._(items, sorted);
}
factory TokenizedFilter.remove({
required Iterable<T> items,
required ToString<T> toString,
required String query,