Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

How can I optimize this switch statement?

I try to use in my app, simple comparator to filter some data with passing string filter instead function as eg. passed to [].filter Comparator should return function which will be a filter.

   var comparator = function( a, b, c ) { 
        switch( b ){
            case '>=': return function() { return this[a] >= c;}; break;
            case '<=': return function() { return this[a] <= c;}; break;
            case '<':  return function() { return this[a] < c;}; break;
            case '>':  return function() { return this[a] > c;}; break;
            case '=':  return function() { return this[a] == c;}; break;
            case '==': return function() { return this[a] === c;}; break;
            case '!=': return function() { return this[a] != c;}; break;
            default: return null;
        };

    }

Assume that i get this function by:

  var filterFn = comparator.apply({}, /(.+)(=|>=|<=|<|>|!=|==|!==)(.+)/.exec( "id<4" ).slice(1) );


  someModel = someModel.objects.filter( filterFn );

The target it will look:

   someModel.get = function( filter ){ 
      return new Model(  
           this.objects.filter(
               comparator.apply({}, /(.+)(=|>=|<=|<|>|!=|==|!==)(.+)/.exec( "id<4" ).slice(1) 
           ) 
      );
   };
   var filtered = someModel.get( "id<4" );

Question is - I assume that it will be a lot more operators and I have no idea how to write it more simply.

Using Eval is out of question.

This code didn't was both executed and tested I wrote it just to show what I mean.

like image 359
abuduba Avatar asked Jan 18 '23 20:01

abuduba


1 Answers

Store every function in an object, either pre-defined, or dynamically.

If you want to dyanmically create the set of functions, define the comparator object as shown below. I assumed that you did not extend the Object.prototype. If you did, operators.hasOwnProperty(property) has to be used within the first loop.

// Run only once
var funcs = {};   // Optionally, remove `funcs` and swap `funcs` with `operators`
var operators = { // at the first loop.
    '>=': '>=',
    '<=': '<=',
    '<' :  '<',
    '>' :  '>',
    '=' : '==', //!!
    '==':'===', //!!
    '!=': '!='
}; // Operators

// Function constructor used only once, for construction
for (var operator in operators) {
    funcs[operator] = Function('a', 'c',
                       'return function() {return this[a] ' + operator + ' c};');
}

// Run later
var comparator = function(a, b, c) {
    return typeof funcs[b] === 'function' ? funcs[b](a, c) : null;
};

When comparator is invoked, the returned function looks like:

function() {  return this[a] < c;   }// Where a, c are pre-determined.

This method can be implemented in this way (demo at JSFiddle):

// Assumed that funcs has been defined
function implementComparator(set, key, operator, value) {
    var comparator, newset = [], i;

    if (typeof funcs[operator] === 'function') {
        comparator = funcs[operator](key, value);
    } else { //If the function does not exist...
        throw TypeError("Unrecognised operator");
    }

    // Walk through the whole set
    for (i = 0; i < set.length; i++) {
        //  Invoke the comparator, setting `this` to `set[i]`. If true, push item
        if (comparator.call(set[i])) {
            newset.push(set[i]);
        }
    }
    return newset;
}
var set = [ {meow: 5}, {meow: 3}, {meow: 4}, {meow: 0}, {meow: 9}]
implementComparator( set , 'meow', '<=', 5);
// equals: [ {meow: 5}, {meow: 3}, {meow: 4}, {meow: 0} ]

For clarification, I constructed this answer, while keeping the following in mind:

  • The OP requests an simple, easily extensible method with an unknown/dynamic set of operators.
  • The code is based on the pseudo-code at the OP, without changing anything which could affect the intent of the OP. With some adjustments, this function can also be used for Array.prototype.filter or Array.prototype.sort.
  • eval (or Function) should not be used at every call to comparator
like image 155
Rob W Avatar answered Jan 29 '23 03:01

Rob W