如何根据一系列数字过滤数组?

时间:2014-05-30 02:02:08

标签: javascript html arrays

我有一个使用此函数过滤的数组:

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 }); 

我有一堆用户可以在选择中选择的选项。持续时间,这就是我所拥有的:

<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>

但该过滤器基于准确的标准。我想在arr中过滤1到3或6到10之间的浮点数。我还希望能够运行我在其中看到的其他过滤器,包括dep,arr,car,epi,dur。我有什么方法可以做到这一点吗?

2 个答案:

答案 0 :(得分:7)

使用array.filter进行回调。下面的代码使用一个字典,其中的条目对应于选项值。

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 ]
);

答案 1 :(得分:1)

假设我了解你的需求,那该怎么办:

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>

数据:

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);

这是一个非常大的功能,但它是完全可扩展的。您可以使用所需的任何值和任何标准,只要您尊重l<max>值中的<min>to<max>m<min><select>语法。

函数的第一部分解析标准值,以获得每个值的最小值或/和最大值。第二部分是将数据数组的每个值与它们进行比较。

如果您有任何疑问,请不要犹豫。