11

I have an array that I filter with this function:

function filter(arr, criteria) {
    return arr.filter(function(obj) {
        return Object.keys(criteria).every(function(c) {
            return !(criteria[c]) || obj[c] == criteria[c];
        });
    });
}

var arr = filter(arr, { dep: dv, arr: av, car: cv, epi: acv, dur: dv }); 

And I have a bunch of options that the user can choose from in the select. For duration, here is what I have:

<select name="duration" id="duration">
  <option selected disabled hidden value="">-</option>
  <option value="l1">Less than 1 hour</option>
  <option value="1to3">1 to 3 hours</option>
  <option value="3to6">3 to 6 hours</option>
  <option value="6to10">6 to 10 hours</option>
  <option value="m10">More than 10 hours</option>
</select>

But that filter is based on exact criteria. I want to filter float numbers in arr that are between 1 and 3 or 6 and 10. I also want to be able to run my other filters that you see up there with dep, arr, car, epi, dur. Is there any way I can do this?

4
  • Can you just set the value to 1, 2, 3, 4, 5 etc. and sort using those numbers? Commented May 30, 2014 at 2:05
  • @dcclassics Okay, but how could I sort? Commented May 30, 2014 at 2:07
  • 2
    try array.filter(function(a){return a>=3&&a<=6}). for [1,2,3,3.1,4,6.1], it will return [3,3.1,4] Commented May 30, 2014 at 2:08
  • @user1494396 Yes, but how I do I use that in my code? Commented May 30, 2014 at 22:25

2 Answers 2

8

Use array.filter with a callback. The code below uses a dictionary with entries corresponding to option values.

var myArray = [1,2,3,3.1,Math.PI,4,4.3,6.1]; //sample array
//Dictionary from option values to functions (JS objects work like hashtables)
var options = {
  "l1":   function(a){return a.duration<1;},
  "1to3": function(a){return a.duration>=1 && a.duration<3;},
  "3to6": function(a){return a.duration>=3 && a.duration<=6;},
...
//When you need to filter the array, do it like so:
var myNewArray = myArray.filter(
  options[ document.getElementById('duration').selectedOptions[0].value ]
);
Sign up to request clarification or add additional context in comments.

7 Comments

Awesome. I have a quick question. I have an array with objects { duration: 1, accel: 'fast' }. So, how do I just filter the duration portion of the array?
Just use return a.duration >= whatever in the body of your filter.
What? I don't understand.
okay, I've edited the code above to depend on the object's duration property. I recommend you look at this link: array.filter
That gives me this error Uncaught TypeError: undefined is not a function on this line ` var arr = arr.filter(options[ document.getElementById('duration').selectedOptions[0].value ]);`
|
1

Assuming I understood your needs, what about that :

jsFiddle

HTML :

<select name="duration" id="duration">
    <option selected value="">Duration</option>
    <option value="l1">Less than 1 hour</option>
    <option value="1to3">1 to 3 hours</option>
    <option value="3to6">3 to 6 hours</option>
    <option value="6to10">6 to 10 hours</option>
    <option value="m10">More than 10 hours</option>
</select>
<select name="acceleration" id="acceleration">
    <option selected value="">Acceleration</option>
    <option value="l2">Less than 2m/s²</option>
    <option value="2to5">2 to 5m/s²</option>
    <option value="5to10">5 to 10m/s²</option>
    <option value="10to15">10 to 15m/s²</option>
    <option value="m15">More than 15m/s²</option>
</select>

The data :

var data = [
    {duration:1.2, acceleration:5.7, name:'elt1'},
    {duration:12, acceleration:1.5, name:'elt2'},
    {duration:3, acceleration:7.8, name:'elt3'},
    {duration:5.4789, acceleration:9.6597, name:'elt4'},
    {duration:0.5, acceleration:12.154, name:'elt5'},
    {duration:(15/7), acceleration:20.32, name:'elt6'},
    {duration:9.81, acceleration:7.123, name:'elt7'},
    {duration:10, acceleration:0.3265, name:'elt8'},
    {duration:5, name:'elt9'} //never selected if there is an "acceleration" filter 
    ];

JS :

var filterData = function(arr, criterias){

    // First : parse the criterias
    var realCriterias = {}, tmp;
    var lessThan = /^l(.+)$/, between = /^(.+)to(.+)$/, moreThan = /^m(.+)$/;
    for (var i in criterias){
        if ("" === criterias[i]);
        tmp = criterias[i].match(lessThan);
        if (tmp) { 
            realCriterias[i] = {max:parseFloat(tmp[1])}; 
            continue;
        }
        tmp = criterias[i].match(between);
        if (tmp) { 
            realCriterias[i] = {min:parseFloat(tmp[1]), max:parseFloat(tmp[2])}; 
            continue;
        }
        tmp = criterias[i].match(moreThan);
        if (tmp) { 
            realCriterias[i] = {min:parseFloat(tmp[1])}; 
        }
    }
    console.log('Real criterias', realCriterias);

    // Then : apply them to arr
    var results = [], elt, cri;
    nextdata:
    for (var i=0; i< arr.length; i++){
        elt = arr[i];
        for (var j in realCriterias){
            if (!elt[j]) continue nextdata; // if criteria does not exits on elt, we break this loop and start again with next element
            cri = realCriterias[j];
            if ((undefined === cri.min && elt[j] >= cri.max) || //"less than" criteria and value is too big
                (undefined === cri.max && elt[j] <= cri.min) || //"more than" criteria and value is too small
                (elt[j] > cri.max || elt[j] < cri.min) // "between" criteria and value is not between min and max (included)
               ) {
                continue nextdata; // we break this loop and start again with next element
            }
        }
        results.push(elt);
    }

    return results;

}

var criterias = {
    duration:$('#duration').val()||'', 
    acceleration:$('#acceleration').val()||''
};
var results = filterData(data , criterias);

It is quite a big function, but it is completely scalable. You can use any values and any criterias you need, as long as you respect the syntax l<max>, <min>to<max> and m<min> in your <select> values.

The first part of the function parses the criteria values to get min or/and max value for each of them. And the second part is just about comparing each value of the data array to them.

Do not hesitate if you have any questions.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.