react / wstein / node_modules / browserify / node_modules / module-deps / node_modules / detective / node_modules / escodegen / node_modules / optionator / node_modules / fast-levenshtein / levenshtein.js
80642 views(function() {1'use strict';23/**4* Extend an Object with another Object's properties.5*6* The source objects are specified as additional arguments.7*8* @param dst Object the object to extend.9*10* @return Object the final object.11*/12var _extend = function(dst) {13var sources = Array.prototype.slice.call(arguments, 1);14for (var i=0; i<sources.length; ++i) {15var src = sources[i];16for (var p in src) {17if (src.hasOwnProperty(p)) dst[p] = src[p];18}19}20return dst;21};2223/**24* Based on the algorithm at http://en.wikipedia.org/wiki/Levenshtein_distance.25*/26var Levenshtein = {27/**28* Calculate levenshtein distance of the two strings.29*30* @param str1 String the first string.31* @param str2 String the second string.32* @return Integer the levenshtein distance (0 and above).33*/34get: function(str1, str2) {35// base cases36if (str1 === str2) return 0;37if (str1.length === 0) return str2.length;38if (str2.length === 0) return str1.length;3940// two rows41var prevRow = new Array(str2.length + 1),42curCol, nextCol, i, j, tmp;4344// initialise previous row45for (i=0; i<prevRow.length; ++i) {46prevRow[i] = i;47}4849// calculate current row distance from previous row50for (i=0; i<str1.length; ++i) {51nextCol = i + 1;5253for (j=0; j<str2.length; ++j) {54curCol = nextCol;5556// substution57nextCol = prevRow[j] + ( (str1.charAt(i) === str2.charAt(j)) ? 0 : 1 );58// insertion59tmp = curCol + 1;60if (nextCol > tmp) {61nextCol = tmp;62}63// deletion64tmp = prevRow[j + 1] + 1;65if (nextCol > tmp) {66nextCol = tmp;67}6869// copy current col value into previous (in preparation for next iteration)70prevRow[j] = curCol;71}7273// copy last col value into previous (in preparation for next iteration)74prevRow[j] = nextCol;75}7677return nextCol;78},7980/**81* Asynchronously calculate levenshtein distance of the two strings.82*83* @param str1 String the first string.84* @param str2 String the second string.85* @param cb Function callback function with signature: function(Error err, int distance)86* @param [options] Object additional options.87* @param [options.progress] Function progress callback with signature: function(percentComplete)88*/89getAsync: function(str1, str2, cb, options) {90options = _extend({}, {91progress: null92}, options);9394// base cases95if (str1 === str2) return cb(null, 0);96if (str1.length === 0) return cb(null, str2.length);97if (str2.length === 0) return cb(null, str1.length);9899// two rows100var prevRow = new Array(str2.length + 1),101curCol, nextCol,102i, j, tmp,103startTime, currentTime;104105// initialise previous row106for (i=0; i<prevRow.length; ++i) {107prevRow[i] = i;108}109110nextCol = 1;111i = 0;112j = -1;113114var __calculate = function() {115// reset timer116startTime = new Date().valueOf();117currentTime = startTime;118119// keep going until one second has elapsed120while (currentTime - startTime < 1000) {121// reached end of current row?122if (str2.length <= (++j)) {123// copy current into previous (in preparation for next iteration)124prevRow[j] = nextCol;125126// if already done all chars127if (str1.length <= (++i)) {128return cb(null, nextCol);129}130// else if we have more left to do131else {132nextCol = i + 1;133j = 0;134}135}136137// calculation138curCol = nextCol;139140// substution141nextCol = prevRow[j] + ( (str1.charAt(i) === str2.charAt(j)) ? 0 : 1 );142// insertion143tmp = curCol + 1;144if (nextCol > tmp) {145nextCol = tmp;146}147// deletion148tmp = prevRow[j + 1] + 1;149if (nextCol > tmp) {150nextCol = tmp;151}152153// copy current into previous (in preparation for next iteration)154prevRow[j] = curCol;155156// get current time157currentTime = new Date().valueOf();158}159160// send a progress update?161if (null !== options.progress) {162try {163options.progress.call(null, (i * 100.0/ str1.length));164} catch (err) {165return cb('Progress callback: ' + err.toString());166}167}168169// next iteration170setTimeout(__calculate(), 0);171};172173__calculate();174}175176};177178// amd179if (typeof define !== "undefined" && define !== null && define.amd) {180define(function() {181return Levenshtein;182});183}184// commonjs185else if (typeof module !== "undefined" && module !== null) {186module.exports = Levenshtein;187}188// web worker189else if (typeof self !== "undefined" && typeof self.postMessage === 'function' && typeof self.importScripts === 'function') {190self.Levenshtein = Levenshtein;191}192// browser main thread193else if (typeof window !== "undefined" && window !== null) {194window.Levenshtein = Levenshtein;195}196}());197198199200