How do I filter an array based on a range of numbers?

后端 未结 2 671
南笙
南笙 2021-01-11 17:26

I have an array that I filter with this function:

function filter(arr, criteria) {
    return arr.filter(function(obj) {
        return Object.keys(criteria)         


        
相关标签:
2条回答
  • 2021-01-11 18:05

    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.

    0 讨论(0)
  • 2021-01-11 18:11

    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 ]
    );
    
    0 讨论(0)
提交回复
热议问题