I am faced with a scenario where I need to filter and categorize an array of objects based on multiple conditions. The challenge arises from the fact that there are more than one condition, and I want the array to be split into several groups accordingly. Each group should match a specific condition, with the last group containing all objects that do not meet any of the conditions.
Initially, my approach involved using multiple .filter functions...
var array = [{
name: 'X',
age: 18
}, {
name: 'Y',
age: 18
}, {
name: 'Z',
age: 20
}, {
name: 'M',
age: 20
}, {
name: 'W',
age: 5
}, {
name: 'W',
age: 10
}];
//objects with age 18
var matchedConditional1 = array.filter(function(x){
return x.age === 18;
});
//objects with age 20
var matchedConditional2 = array.filter(function(x){
return x.age === 20;
});
//objects with neither age 18 nor 20
var matchedNoConditional = array.filter(function(x){
return (x.age !== 18 && x.age !== 20);
});
However, I found this approach redundant and not very reusable at all.
So, I decided to modify the function based on Brendan's answer, resulting in the following solution.
Array.prototype.group = function(f) {
var matchedFirst = [],
matchedSecond = [],
unmatched = [],
i = 0,
l = this.length;
for (; i < l; i++) {
if (f.call(this, this[i], i)[0]) {
matchedFirst.push(this[i]);
} else if (f.call(this, this[i], i)[1]) {
matchedSecond.push(this[i]);
} else {
unmatched.push(this[i]);
}
}
return [matchedFirst, matchedSecond, unmatched];
};
var filteredArray = array.group(function(x){
return [x.age === 18, x.age === 20];
});
This new method returns an array with three arrays. The first array contains objects matching the first condition, the second array contains objects matching the second condition, and the last array contains objects that do not fit into either condition.
Although this solution works well for situations with only two conditions, it is limited in its reusability for scenarios requiring more than two conditions.
I am seeking a solution that allows me to specify any number of conditions and receive the corresponding arrays along with an additional array for unmatched objects.
Note: The input and output formats do not necessarily have to be arrays, but for clarity, I chose to represent them as such. The method does not have to follow the .filter model; it could also be implemented as a .map or .reduce function. Any suggestions are welcome.
Edit: Following @slebetman's suggestion, it would be beneficial if the solution supported code composability.