15

I want to select the objects based on the properties of the objects, but not always the same properties. In other words:

arr = [
    { name: "joe",   age21: 1 },
    { name: "nick",  age21: 0 },
    { name: "blast", age21: 1 }
];

arr.filter(function(item) {
    return (item.name === "nick" && item.age21 === 1);
});

But sometimes I just want to filter on name for example:

arr.filter(function(item) {
    return (item.name === "nick");
});

What I want to do is generalize this so that the list of parameters can be passed to the function. I've come up with the following, but it's slow and I'm wondering if there is a better way:

filterParams = function(arr, params) {
    var new_array = arr.filter(function(item) {
        var select = 1
        for(obj in params) { //create the filter criteria based on varying set of parameters
            var select = select && params[obj] === item[obj];
        }
        return select;
    });
    return new_array;
}

Then you could call it with: filterParams(arr, {name: "nick", age21: 1});

or with: filterParams(arr, {name: "nick"});

and it would work either way.

In case you're wondering, I'm doing this because I have different data sets that I want to run through the same routine, so the filter properties need to be generalized so that I can filter on properties specific to each dataset.

Thanks!

4

1 回答 1

46

这是一种功能性方法,适用于给定对象的任意数量的属性:

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

例如:

var arr = [
  { name: 'Steve', age: 18, color: 'red' },
  { name: 'Louis', age: 21, color: 'blue' }, //*
  { name: 'Mike', age: 20, color: 'green' },
  { name: 'Greg', age: 21, color: 'blue' }, //*
  { name: 'Josh', age: 18, color: 'red' }
];

console.log(filter(arr, { age: 21, color: 'blue' }));
//^ {age:21, color:'blue', name:'Louis}
//  {age:21, color:'blue', name:'Greg'}

不确定您的性能问题,但这应该没问题。

编辑:您可以使用正则表达式使其更强大,如下所示:

function filter(arr, criteria) {
  return arr.filter(function(obj) {
    return Object.keys(criteria).every(function(c) {
      return new RegExp(criteria[c]).test(obj[c]);
    });
  });
}

console.log(filter(arr, { age: /^2\d$/, color: /^(red|blue)$/ }));
//^ Louis, Greg                --^-- twenty-something
//                                               ----^---- red OR blue
于 2013-06-14T00:15:33.240 回答