fuzzySearch function

List<FuzzySearchUtils> fuzzySearch(
  1. String query,
  2. List<String> candidates, {
  3. int maxDistance = 2,
  4. double minScore = 0.0,
})

Searches candidates for query; returns matches sorted by match score descending.

Score combines token overlap and edit-distance ratio. maxDistance caps per-token edit distance; minScore excludes results below that threshold.

Implementation

List<FuzzySearchUtils> fuzzySearch(
  String query,
  List<String> candidates, {
  int maxDistance = 2,
  double minScore = 0.0,
}) {
  final String q = query.trim().toLowerCase();
  if (q.isEmpty) {
    return candidates.asMap().entries.map((e) => FuzzySearchUtils(e.key, e.value, 1.0)).toList();
  }
  final List<String> qTokens = q.split(RegExp(r'\s+'));
  final List<FuzzySearchUtils> out = <FuzzySearchUtils>[];
  for (int i = 0; i < candidates.length; i++) {
    final String c = candidates[i];
    final String cLower = c.toLowerCase();
    final List<String> cTokens = cLower.split(RegExp(r'\s+'));
    double score = 0.0;
    for (final String qt in qTokens) {
      double best = 0.0;
      for (final String ct in cTokens) {
        final int d = LevenshteinUtils.distance(qt, ct);
        if (d <= maxDistance) {
          final double r = LevenshteinUtils.ratio(qt, ct);
          if (r > best) best = r;
        }
      }
      score += best;
    }
    final double norm = score / qTokens.length;
    if (norm >= minScore) out.add(FuzzySearchUtils(i, c, norm));
  }
  out.sort((FuzzySearchUtils a, FuzzySearchUtils b) => b.score.compareTo(a.score));
  return out;
}