How can I optimize this switch statement?

I am trying to use a simple comparator in my application to filter some data with a passing string filter instead of a function, for example. passed [].filter comparator should return a function that 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; }; } 

Suppose I get this function:

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

The goal 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: I assume that there will be many more operators, and I have no idea how to write it easier.

Using Eval is out of the question.

This code has not been executed and tested. I wrote it to show what I mean.

+4
source share
3 answers

Store each function in an object, either predefined or dynamically.

If you want to create a feature set, create a comparator object, as shown below. I assumed that you did not extend Object.prototype . If you have done this, operators.hasOwnProperty(property) should be used in 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 called, the returned function looks like this:

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

This method can be implemented this way ( demo in 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 built this answer, given the following:

  • The OP requests a simple, easily extensible method with an unknown / dynamic set of statements.
  • The code is based on the pseudo-code in the OP, without changing anything that could affect the intent of the OP. With some settings, this function can also be used for Array.prototype.filter or Array.prototype.sort .
  • eval (or Function ) should not be used with every call to comparator
+5
source

Do not do it so dynamically ... it would be much more efficient to create functions only once, and not every time they are called, as this will create a new function and therefore a memory leak every time the comparison is done.

 var comparator = { ">=": function(a, b) { return a >= b;}, "<=": function(a, b) { return a <= b;}, "add": function(a, b) { return a + b; }, compare: function(typeString, a, b){ if(comparator.hasOwnProperty(typeString) == true){ var theFunction = comparator[typeString]; return theFunction(a, b); } else{ alert("typeString '" + typeString + "' not supported."); } }, }; var test = comparator.compare(">=", 5, 4); 
+2
source
 var comparator = (function () { var fns = { '>=': function (a, c) { return a >= c; }, '<=': function (a, c) { return a <= c; }, '<': function (a, c) { return a < c; }, '>': function (a, c) { return a > c; }, '=': function (a, c) { return a == c; }, '==': function (a, c) { return a === c; }, '!=': function (a, c) { return a != c; } }; return function (b) { return fns.hasOwnProperty(b) ? fns[b] : null; }; }()); 

At this point, you can see that nothing is more efficient than the inline expression. I don’t understand why you think you need to be so dynamic in advance.

+2
source

Source: https://habr.com/ru/post/1389805/


All Articles