1 /** 2 * Copyright (c) 2012. 3 * Licensed under the MIT License. 4 * See LICENSE for detailed information. 5 * 6 * JavaScript 7 * 8 * @fileoverview Methods to compute string metrics. 9 * @version 0.3.0 10 * @author Jonathan Ruttan <jonruttan@iwastenotsystems.com> 11 * @license http://www.opensource.org/licenses/mit-license.php The MIT License. 12 * @package String.metrics 13 * 14 */ 15 // TODO: Finalize Node namespace settings 16 // +[Fix String.metrics namespace hack]--JR 17 (function(exports) { 18 'use strict'; 19 20 /** 21 * @namespace Contains methods to compute string metrics. 22 * @name String.metrics 23 */ 24 var fns = exports.metrics = { 25 /** 26 * Compute the distance between two strings as a fraction of the length 27 * of the longer of the two strings. 28 * 29 * @public 30 * @memberOf String.metrics 31 * @param {String} str1 One of the strings to score against. 32 * @param {String} str2 One of the strings to score against. 33 * @param {Number|Function} distance 34 * An integer distance between strings, 35 * or a function to compute the distance. 36 * @return {Number} Returns the computed distance between the 37 * two argument strings as a fraction. 38 */ 39 fraction: function( str1, str2, distance ) { 40 var length = Math.max(str1.length, str2.length); 41 return length ? 1 - (typeof distance === 'function' ? 42 distance( str1, str2 ) : distance) / length : 1; 43 }, 44 45 /** 46 * Compute the Levenshtein distance between two strings. 47 * 48 * @public 49 * @memberOf String.metrics 50 * @see Source: <a href="http://en.wikibooks.org/wiki/Algorithm_Implementation/Strings/Levenshtein_distance#JavaScript">Wikibooks:Algorithm Implementation/Strings/Levenshtein distance</a> 51 * @see Wikipedia: <a href="http://en.wikipedia.org/wiki/Levenshtein_distance">Levenshtein distance</a> 52 * @param {String} str1 One of the strings to score against. 53 * @param {String} str2 One of the strings to score against. 54 * @return {Number} Returns the computed Levenshtein distance 55 * between the two argument strings. 56 */ 57 levenshteinDistance: function(str1, str2) { 58 if (str1.length === 0) return str2.length; 59 if (str2.length === 0) return str1.length; 60 61 var matrix = []; 62 63 // increment along the first column of each row 64 var i; 65 for (i = 0; i <= str2.length; i++) { 66 matrix[i] = [i]; 67 } 68 69 // increment each column in the first row 70 var j; 71 for (j = 0; j <= str1.length; j++) { 72 matrix[0][j] = j; 73 } 74 75 // Fill in the rest of the matrix 76 for (i = 1; i <= str2.length; i++) { 77 for (j = 1; j <= str1.length; j++) { 78 if (str2.charAt(i - 1) == str1.charAt(j - 1)) { 79 matrix[i][j] = matrix[i - 1][j - 1]; 80 } else { 81 matrix[i][j] = Math.min(matrix[i - 1][j - 1] + 1, // substitution 82 Math.min(matrix[i][j - 1] + 1, // insertion 83 matrix[i - 1][j] + 1)); // deletion 84 } 85 } 86 } 87 88 return matrix[str2.length][str1.length]; 89 }, 90 91 /** 92 * Compute the Levenshtein distance between two strings as a fraction 93 * of the length of the longer of the two strings. 94 * . 95 * 96 * @public 97 * @memberOf String.metrics 98 * @param {String} str1 One of the strings to score against. 99 * @param {String} str2 One of the strings to score against. 100 * @return {Number} Returns the computed distance between the two 101 * argument strings as a fraction. 102 */ 103 levenshteinFraction: function( str1, str2 ) { 104 return exports.metrics.fraction(str1, str2, 105 exports.metrics.levenshteinDistance); 106 } 107 }; 108 })(typeof exports === 'undefined' ? String : exports); 109