Files
receipity/lib/utils/fuzzy.dart
T

41 lines
1.2 KiB
Dart

/// Lightweight fuzzy matching for product search.
library;
String _normalize(String value) =>
value.trim().toLowerCase().replaceAll(RegExp(r'\s+'), ' ');
/// True when [query] fuzzily matches [text].
bool fuzzyMatch(String query, String text) {
final q = _normalize(query);
if (q.isEmpty) return true;
final t = _normalize(text);
if (t.contains(q)) return true;
for (final word in q.split(' ')) {
if (word.isEmpty) continue;
if (!t.contains(word) && !_subsequence(word, t)) return false;
}
if (q.contains(' ')) return true;
return _subsequence(q, t);
}
/// Higher is better. Null when [query] does not match.
int? fuzzyScore(String query, String text) {
final q = _normalize(query);
if (q.isEmpty) return 0;
final t = _normalize(text);
if (t == q) return 1000;
if (t.startsWith(q)) return 800;
if (t.contains(q)) return 600 - t.indexOf(q);
if (!fuzzyMatch(q, t)) return null;
return 200 - (t.length - q.length).abs().clamp(0, 150);
}
bool _subsequence(String query, String text) {
var i = 0;
for (var c = 0; c < text.length && i < query.length; c++) {
if (text.codeUnitAt(c) == query.codeUnitAt(i)) i++;
}
return i == query.length;
}