Permalink
Browse files

Use match() operator for regex

  • Loading branch information...
1 parent b16713b commit e48ec9d57b835cb42cb41de4cdbf4cdd2463bee5 @kriszyp committed Dec 1, 2010
Showing with 39 additions and 51 deletions.
  1. +36 −46 lib/js-array.js
  2. +3 −5 test/js-array.js
View
@@ -46,10 +46,13 @@ exports.operators = {
});
return this;
},
+ match: filter(function(value, regex){
+ return new RegExp(regex).test(value);
+ }),
"in": filter(function(value, values){
return values.indexOf(value) > -1;
}),
- "out": filter(function(value, values){
+ out: filter(function(value, values){
return values.indexOf(value) == -1;
}),
contains: filter(function(array, value){
@@ -345,57 +348,44 @@ function query(query, options, target){
var parameters = options.parameters || [];
var js = "";
function queryToJS(value){
- if(value && typeof value === "object" && !(value instanceof Array)){
- var jsOperator = exports.jsOperatorMap[value.name];
- if(jsOperator){
- // item['foo.bar'] ==> (item && item.foo && item.foo.bar && ...)
- var path = value.args[0];
- var target = value.args[1];
- if (typeof target == "undefined"){
- var item = "item";
- target = path;
- }else if(path instanceof Array){
- var item = "item";
- var escaped = [];
- for(var i = 0;i < path.length; i++){
- escaped.push(stringify(path[i]));
- item +="&&item[" + escaped.join("][") + ']';
+ if(value && typeof value === "object"){
+ if(value instanceof Array){
+ return '[' + value.map(queryToJS) + ']';
+ }else{
+ var jsOperator = exports.jsOperatorMap[value.name];
+ if(jsOperator){
+ // item['foo.bar'] ==> (item && item.foo && item.foo.bar && ...)
+ var path = value.args[0];
+ var target = value.args[1];
+ if (typeof target == "undefined"){
+ var item = "item";
+ target = path;
+ }else if(path instanceof Array){
+ var item = "item";
+ var escaped = [];
+ for(var i = 0;i < path.length; i++){
+ escaped.push(stringify(path[i]));
+ item +="&&item[" + escaped.join("][") + ']';
+ }
+ }else{
+ var item = "item&&item[" + stringify(path) + "]";
}
- }else{
- var item = "item&&item[" + stringify(path) + "]";
- }
- // comparison to regexps are special: we cope with eq(), ne(), the others coerce regexp to string
- if (value.args[1] instanceof RegExp) {
- if (jsOperator === '===' || jsOperator === '!==') {
- // N.B. matching requires String
- item = 'String('+item + '||"")';
- if (jsOperator === '!==') item = '!'+item;
- jsOperator = '.match('+value.args[1]+')&&""===';
- target = '';
+ // use native Array.prototype.filter if available
+ var condition = item + jsOperator + queryToJS(target);
+ if (typeof Array.prototype.filter === 'function') {
+ return "(function(){return this.filter(function(item){return " + condition + "})})";
+ //???return "this.filter(function(item){return " + condition + "})";
} else {
- // TODO: more elegant?
- // FIXME: require()ing ./query at top level makes circular dep and ./query.knownOperators becomes undefined
- target = QUERY.encodeValue(target).split(':').slice(1).join(':');
- // TODO: RECONSIDER, as under nodules require() is 10 times slower
- // PLUS is breaks client-side require()
- //value.args[1] = require('./query').encodeValue(value.args[1]).split(':').slice(1).join(':');
+ return "(function(){var filtered = []; for(var i = 0, length = this.length; i < length; i++){var item = this[i];if(" + condition + "){filtered.push(item);}} return filtered;})";
}
+ }else{
+ return "(function(){return op('" + value.name + "').call(this" +
+ (value && value.args && value.args.length > 0 ? (", " + value.args.map(queryToJS).join(",")) : "") +
+ ")})";
}
- // use native Array.prototype.filter if available
- var condition = item + jsOperator + queryToJS(target);
- if (typeof Array.prototype.filter === 'function') {
- return "(function(){return this.filter(function(item){return " + condition + "})})";
- //???return "this.filter(function(item){return " + condition + "})";
- } else {
- return "(function(){var filtered = []; for(var i = 0, length = this.length; i < length; i++){var item = this[i];if(" + condition + "){filtered.push(item);}} return filtered;})";
- }
- }else{
- return "(function(){return op('" + value.name + "').call(this" +
- (value && value.args && value.args.length > 0 ? (", " + value.args.map(queryToJS).join(",")) : "") +
- ")})";
}
}else{
- return typeof value === "number" ? value : stringify(value);
+ return typeof value === "string" ? stringify(value) : value;
}
}
var evaluator = eval("(function(target){return " + queryToJS(query) + ".call(target);})");
View
@@ -31,12 +31,10 @@ exports.testFiltering = function() {
assert.equal(executeQuery("excludes(tags,ne(fun))", {}, data).length, 1);
assert.equal(executeQuery("excludes(tags,ne(even))", {}, data).length, 0);
// eq() on re: should trigger .match()
- assert.deepEqual(executeQuery("price=re:10", {}, data), [data[0]]);
+ assert.deepEqual(executeQuery("price=match=10", {}, data), [data[0]]);
// ne() on re: should trigger .not(.match())
- assert.deepEqual(executeQuery("ne(price,re:10)", {}, data), [data[1]]);
- // other comparisons to re: should treat regexp as string
- assert.deepEqual(executeQuery("lt(price,re:10)", {}, data), [data[1]]);
- assert.deepEqual(executeQuery("gt(price,re:10)", {}, data), []);
+ assert.deepEqual(executeQuery("name=match=f.*", {}, data), [data[1]]);
+ assert.deepEqual(executeQuery("name=match=glob:f*", {}, data), [data[1]]);
};
exports.testFiltering1 = function() {

0 comments on commit e48ec9d

Please sign in to comment.