Как фильтровать массив объектов javascript с переменными параметрами
Я хочу выбрать объекты, основанные на свойствах объектов, но не всегда одинаковые свойства. Другими словами:
arr = [
{ name: "joe", age21: 1 },
{ name: "nick", age21: 0 },
{ name: "blast", age21: 1 }
];
arr.filter(function(item) {
return (item.name === "nick" && item.age21 === 1);
});
Но иногда я просто хочу фильтровать по имени, например:
arr.filter(function(item) {
return (item.name === "nick");
});
Что я хочу сделать, это обобщить это так, чтобы список параметров мог быть передан функции. Я придумал следующее, но это медленно, и мне интересно, есть ли лучший способ:
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;
}
Затем вы можете позвонить ему: filterParams(arr, {name: "nick", age21: 1});
или с: filterParams(arr, {name: "nick"});
и он будет работать в любом случае.
В случае, если вам интересно, я делаю это, потому что у меня разные наборы данных, которые я хочу запускать с помощью одной и той же процедуры, поэтому свойства фильтра должны быть обобщены, чтобы я мог фильтровать свойства, специфичные для каждого набора данных.
Спасибо!
Ответы
Ответ 1
Вот функциональный подход, который должен работать для любого количества свойств, заданных объектом:
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