Skip to content

Commit

Permalink
implemented FastMatcher
Browse files Browse the repository at this point in the history
  • Loading branch information
dtao committed Mar 25, 2014
1 parent 2b75ece commit a073cc3
Show file tree
Hide file tree
Showing 3 changed files with 118 additions and 0 deletions.
1 change: 1 addition & 0 deletions .gitignore
Original file line number Diff line number Diff line change
@@ -0,0 +1 @@
/node_modules/
96 changes: 96 additions & 0 deletions fastMatcher.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,96 @@
function FastMatcher(list, options) {
this.list = list;
this.options = options || {};
this.matches = this.options.matches || [];

var selector = this.selector = this.createSelector();
this.list.sort(function(x, y) {
return compare(selector(x), selector(y));
});
}

/**
* @example
* function createSelector(property) {
* return new FastMatcher([], { selector: property }).createSelector();
* }
*
* createSelector()('foo'); // => 'foo'
* createSelector('x')({ x: 'bar'}); // => 'bar'
*/
FastMatcher.prototype.createSelector = function createSelector() {
var selector = this.options.selector;
if (selector) {
return function(x) { return x[selector]; };
}

return function(x) { return x; };
};

/**
* @example
* var fm = new FastMatcher(['ab', 'ac', 'ba', 'bc']);
*
* fm.getMatches('a'); // => ['ab', 'ac']
*/
FastMatcher.prototype.getMatches = function getMatches(prefix) {
var limit = this.options.limit || 25,
selector = this.selector;

var list = this.list,
matches = this.matches,
index = this.findIndex(prefix);

matches.length = 0;
while (index < list.length && matches.length < limit && startsWith(selector(list[index]), prefix)) {
matches.push(list[index++]);
}

return matches;
};

FastMatcher.prototype.findIndex = function findIndex(prefix) {
var list = this.list,
selector = this.selector,
lower = 0,
upper = list.length,
i;

while (lower < upper) {
i = (lower + upper) >>> 1;
if (compare(selector(list[i]), prefix) === -1) {
lower = i + 1;
} else {
upper = i;
}
}
return lower;
};

/**
* @private
* @example
* compare('foo', 'foo'); // => 0
* compare('foo', 'bar'); // => 1
* compare('bar', 'foo'); // => -1
*/
function compare(x, y) {
if (x == y) { return 0; }
return x > y ? 1 : -1;
}

/**
* @private
* @example
* startsWith('foo', 'f'); // => true
* startsWith('bar', 'f'); // => false
* startsWith('foo', 'fo'); // => true
* startsWith('foo', 'o'); // => false
*/
function startsWith(string, prefix) {
return string.lastIndexOf(prefix, prefix.length) === 0;
}

if (typeof module === 'object' && (module && module.exports)) {
module.exports = FastMatcher;
}
21 changes: 21 additions & 0 deletions package.json
Original file line number Diff line number Diff line change
@@ -0,0 +1,21 @@
{
"name": "fast-matcher",
"version": "0.1.0",
"description": "Find matches fast",
"main": "fastMatcher.js",
"scripts": {
"test": "autodoc -t fastMatcher.js"
},
"repository": {
"type": "git",
"url": "https://github.com/dtao/fast-matcher"
},
"author": "Dan Tao <[email protected]>",
"license": "MIT",
"bugs": {
"url": "https://github.com/dtao/fast-matcher/issues"
},
"devDependencies": {
"autodoc": "~0.6.1"
}
}

0 comments on commit a073cc3

Please sign in to comment.