All files fuzzy-match.ts

100% Statements 36/36
100% Branches 7/7
100% Functions 1/1
100% Lines 36/36

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 681x 1x 1x                                                       1x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x 10x   10x 9x 8x 8x 8x 8x 8x   9x 8x 8x 8x   9x 8x 8x 8x 8x 8x 9x   10x 10x  
import { diceCoefficient } from './dice-coefficient.ts';
import { levenshteinDistance } from './levenshtein-distance.ts';
import { longestCommonSubstring } from './longest-common-substring.ts';
 
/**
 * Options for the {@link fuzzyMatch} function
 * @group String
 * @category Fuzzy Match
 */
export type FuzzyMatchOptions = {
  /** The comparison will ignore case */
  caseInsensitive?: boolean;
  /** Weight of levenshtein distance */
  weightLevenshteinDistance?: number;
  /** Weight of diceCoefficient */
  weightDiceCoefficient?: number;
  /** Weight of longestCommonSubstring */
  weightLongestCommonSubstring?: number;
};
 
/**
 * Computes a fuzzy similarity score between two strings using a weighted combination
 * of Levenshtein distance, Dice coefficient, and longest common substring metrics.
 * @param input - The input string to compare.
 * @param comparedTo - The string to compare against.
 * @param options - Optional configuration for the comparison.
 * @returns A similarity score between 0 and 1, where 1 indicates a perfect match.
 * @group String
 * @category Fuzzy Match
 */
export function fuzzyMatch(
  input: string,
  comparedTo: string,
  {
    caseInsensitive = true,
    weightLevenshteinDistance = 5,
    weightDiceCoefficient = 3,
    weightLongestCommonSubstring = 2,
  }: FuzzyMatchOptions = {},
): number {
  const len = Math.max(input.length, comparedTo.length);
  let wgt = 0;
  let sum = 0;
 
  if (len) {
    if (weightLevenshteinDistance) {
      sum +=
        weightLevenshteinDistance *
        (1.0 - levenshteinDistance(input, comparedTo, { caseInsensitive }) / len);
      wgt += weightLevenshteinDistance;
    }
 
    if (weightDiceCoefficient) {
      sum += weightDiceCoefficient * diceCoefficient(input, comparedTo, { caseInsensitive });
      wgt += weightDiceCoefficient;
    }
 
    if (weightLongestCommonSubstring) {
      sum +=
        weightLongestCommonSubstring *
        (longestCommonSubstring(input, comparedTo, { caseInsensitive }).length / len);
      wgt += weightLongestCommonSubstring;
    }
  }
 
  return wgt === 0 ? 0 : sum / wgt;
}