pretty good
This commit is contained in:
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user