UNPKG

@woosh/meep-engine

Version:

Pure JavaScript game engine. Fully featured and production ready.

65 lines (53 loc) 2.04 kB
import { assert } from "../../assert.js"; import { min3 } from "../../math/min3.js"; import { string_jaro_distance } from "./string_jaro_distance.js"; /** * Calculate the Jaro-Winkler distance between two strings. * Useful for sorting and fuzzy matching. * * @param {string} first The string to compare * @param {string} second The string to compare with * @returns {number} similarity score, higher value means strings are more similar, between 0 and 1 * * @example * string_jaro_winkler("Hello", "Hello") === 1 * string_jaro_winkler("apple", "orange") === 0.58 * string_jaro_winkler("how are you?", "are you good?") === 0.74 */ export function string_jaro_winkler(first, second) { assert.isString(first, 'first'); assert.isString(second, 'second'); const l1 = first.length; const l2 = second.length; if (l1 === 0 && l2 === 0) { // special case for empty string return 1; } // Calculate the Jaro distance: const similarity = string_jaro_distance(first, second, l1, l2); if (similarity === 0) { // no similarity at all return 0; } // Transform to Jaro-Winkler // Prefix scale gives more favorable ratings to strings that share common prefixes const prefix_scale = 0.1; const prefix = getPrefix(first, second, min3(l1, l2, 4)); return similarity + prefix * prefix_scale * (1 - similarity); } /** * Counts the number of common characters at the beginning of each word up to a maximum of {@link character_limit} * @param {string} a1 The first string to compare * @param {string} a2 The second string to compare * @param {number} character_limit * @returns {number} number of matching characters from the start of the string, up to limit */ function getPrefix(a1, a2, character_limit) { let p = 0; for (; p < character_limit; p++) { if (a1.charAt(p) !== a2.charAt(p)) { return p; } } return ++p; }