Using Underscore.js, I'm trying to group a list of items multiple times, ie
Group by SIZE then for each SIZE, group by CATEGORY...
http://jsfiddle.net/rickysullivan/WTtXP/1/
Ideally, I'd like to have a function or extend _.groupBy()
so that you can throw an array at it with the paramaters to group by.
var multiGroup = ['size', 'category'];
Probably could just make a mixin...
_.mixin({
groupByMulti: function(obj, val, arr) {
var result = {};
var iterator = typeof val == 'function' ? val : function(obj) {
return obj[val];
};
_.each(arr, function(arrvalue, arrIndex) {
_.each(obj, function(value, objIndex) {
var key = iterator(value, objIndex);
var arrresults = obj[objIndex][arrvalue];
if (_.has(value, arrvalue))
(result[arrIndex] || (result[arrIndex] = [])).push(value);
My head hurts, but I think some more pushing needs to go here...
});
})
return result;
}
});
properties = _.groupByMulti(properties, function(item) {
var testVal = item["size"];
if (parseFloat(testVal)) {
testVal = parseFloat(item["size"])
}
return testVal
}, multiGroup);
This is a great use case for the reduce phase of map-reduce. It's not going to be as visually elegant as the multi-group function (you can't just pass in an array of keys to group on), but overall this pattern gives you more flexibility to transform your data. EXAMPLE
But if you just want it in an underscore mixin, here's my stab at it:
Check out this underscore extension: Underscore.Nest, by Irene Ros.
This extension's output will be slightly different from what you specify, but the module is only about 100 lines of code, so you should be able to scan to get direction.
The improvements by joyrexus on bergi's method don't take advantage of the underscore/lodash mixin system. Here it is as a mixin: