I have an array of objects which I would like to filter and divide into groups according to a conditional. The predicament comes because I have more than one conditional, and would like the array to be divided into several arrays. First array matching the first conditional, second array matching second conditional, ... , and the last array containing all objects not matching any conditional.
The first solution that came to mind to this problem was in the form of several .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 or 20
var matchedNoConditional = array.filter(function(x){
return (x.age !== 18 && x.age !== 20);
});
but that seemed redundant and not reusable at all.
So I modified the function on Brendan's answer, and got this.
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 method returns an array with 3 arrays. The first one containing all objects matching the first conditional, second one with objects matching the second conditional, and the last one with objects not matching any of the two.
The problem with this method is that it is limited to two conditionals and hence only three groups of objects. This method actually works for my particular situation for I only have two conditionals, but is not reusable in situations that require more than two.
I would like to be able to give as many conditionals as I want and receiving that amount of arrays plus an extra array with objects not belonging to any group.
Ps. The input and output don't need to be arrays, but I thought that makes more sense. The method doesn't have to be modeled after .filter, it very well could be a .map function or even a .reduce. Any suggestion is appreciated.
Edit: as suggested by @slebetman, it would be great if the answer allowed for code composability.