UNPKG

string-score

Version:

A pure (functional) version of Joshaven Potter's string_score package which doesn't alter the String prototype.

79 lines (67 loc) 2.33 kB
/** * Scores a target string against a query string. * @param {String} target The target string to score the query against. * @param {String} query The query to score against the target string. * @param {Number} fuzzyFactor Optional. A number between 0 and 1 which increases scores of non-perfect matches. * @return {Number} A number between 0 and 1. 0 being no match and 1 being perfect match. */ module.exports = function (target, query, fuzzyFactor) { 'use strict'; // If the string is equal to the word, perfect match. if (target === query) { return 1; } // If it's not a perfect match and is empty return 0. if (query === '') { return 0; } var runningScore = 0; var targetLower = target.toLowerCase(); var targetLen = target.length; var queryLower = query.toLowerCase(); var queryLen = query.length; var startAt = 0; var fuzzies = 1; // Calculate fuzzy factor fuzzyFactor = fuzzyFactor ? 1 - fuzzyFactor : 0; // Walk through query and add up scores. // Code duplication occurs to prevent checking fuzziness inside for loop for (var i = 0; i < queryLen; i+=1) { // Find next first case-insensitive match of a character. var idxOf = targetLower.indexOf(queryLower[i], startAt); if (idxOf === -1) { if (fuzzyFactor) { fuzzies += fuzzyFactor; } else { return 0; } } else { var charScore = 0; if (startAt === idxOf) { // Consecutive letter & start-of-string Bonus charScore = 0.7; } else { charScore = 0.1; // Acronym Bonus // Weighing Logic: Typing the first character of an acronym is as if you // preceded it with two perfect character matches. if (target[idxOf - 1] === ' ') { charScore += 0.8; } } // Same case bonus. if (target[idxOf] === query[i]) { charScore += 0.1; } // Update scores and startAt position for next round of indexOf runningScore += charScore; startAt = idxOf + 1; } } // Reduce penalty for longer strings. var finalScore = 0.5 * (runningScore / targetLen + runningScore / queryLen) / fuzzies; if ((queryLower[0] === targetLower[0]) && (finalScore < 0.85)) { finalScore += 0.15; } return finalScore; };