4

I'm creating a function to filter my javascript objects.

function filter(array,filterName,filterCondition,filterParameter){

    for(var i=0; i< array.length;i++){
        if(array[i][filterName] -<convert FilterCondition here>- filterParameter){

        }
    }

}

and ideally I would like to use it like this:

filter(anArray,"age",">",10)

Is it possible to convert a string comparison operator into a real operator in my if statement?

Terence Chow
  • 10,755
  • 24
  • 78
  • 141

2 Answers2

8

For example, you can use hash like this:

function filter(array,filterName,filterCondition,filterParameter){
    var comparisonOperatorsHash = {
        '<': function(a, b) { return a < b; },
        '>': function(a, b) { return a > b; },
        '>=': function(a, b) { return a >= b; },
        '<=': function(a, b) { return a <= b; },
        '==': function(a, b) { return a == b; },
        '===': function(a, b) { return a === b; },
    };

    var comparisonOperator = comparisonOperatorsHash[filterCondition];

    if (comparisonOperator === undefined) {
        // throw error here
    }

    for(var i=0; i< array.length;i++){
        if(comparisonOperator(array[i][filterName], filterParameter)) {

        }
    }
}
cassln
  • 722
  • 2
  • 6
  • 18
1

eval is evil, but can do anything. It's considered evil if arbitrary input can be passed to it, like user input. But if you control what's in there, it should be safe. More info here.

So you could do:

function filter(array,filterName,filterCondition,filterParameter){
    var results = [];
    for(var i=0; i< array.length;i++){
        if(eval(array[i][filterName] + filterCondition + filterParameter)){
            results.push(array[i]['name'])
        }
    }
    document.body.innerHTML = 'These guys are older than 10: ' + results.join(', ');
}

var anArray = [
  {'name': 'Patrick', 'age': 8 },
  {'name': 'John', 'age': 12 },
  {'name': 'Debora', 'age': 26 },
  {'name': 'Jenna', 'age': 3 },
  {'name': 'Brandon', 'age': 14 },
];

filter(anArray,"age",">",10);

Edit

I've thought of another way without the eval, or an endless switch statement. The trick here is to create a temporary script tag, that will hold a function to check conditions. This will avoid recompiling your function on every iteration of the loop, as it would with eval.

var conditionScript = document.createElement('script');

function filter(array,filterName,filterCondition,filterParameter){
    var results = [];
    prepareCondition(filterCondition,filterParameter);

    for(var i=0; i< array.length;i++){
        if( evalCondition(array[i][filterName]) ){
            results.push(array[i]['name']);
        }
    }

    document.body.innerHTML = 'These guys are older than 10: ' + results.join(', ');
}

function prepareCondition(filterCondition,filterParameter){
    if(conditionScript.parentNode) document.body.removeChild(conditionScript);
    conditionScript.innerText = 'function evalCondition(value){'
                              + '    return value ' + filterCondition + filterParameter
                              + '}';
    document.body.appendChild(conditionScript);
}

var anArray=[
  {'name': 'Patrick', 'age': 8 },
  {'name': 'John', 'age': 12 },
  {'name': 'Debora', 'age': 26 },
  {'name': 'Jenna', 'age': 3 },
  {'name': 'Brandon', 'age': 14 },
];

filter(anArray,"age",">",10);
    
blex
  • 24,941
  • 5
  • 39
  • 72