Skip to content

Instantly share code, notes, and snippets.

@jpbochi
Created September 26, 2012 02:34
Show Gist options
  • Star 2 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jpbochi/3785672 to your computer and use it in GitHub Desktop.
Save jpbochi/3785672 to your computer and use it in GitHub Desktop.
underscore.js extended groupBy with value selector
// The code below will extend underscore.js adding the groupByAndMap function.
// groupByAndMap works like the regular groupBy, but it accepts an optional third "selector" argument.
// The 'selector' is used to select values inside each group.
// As usual in underscore, you can either pass a function or a string with the name of an attribute you want.
// groupByAndMap is useful when you don't want the key to be present in the values inside the group.
// Also, it completely covers the groupBy functionality because the last argument is optional.
// If you want, you can replace groupBy instead of defining a new function.
_.mixin({
groupByAndMap: function(list, keySelector, valueSelector) {
function lookupIterator(val) {
return _.isFunction(val) ? val : function(obj) { return obj[val]; };
};
var keySelectorFunc = lookupIterator(keySelector);
var valueSelectorFunc = valueSelector ? lookupIterator(valueSelector) : _.identity;
return _.foldl(list, function(result, value) {
var key = keySelectorFunc(value);
(result[key] || (result[key] = [])).push(valueSelectorFunc(value));
return result;
}, {});
}
});
// And here is a qunit test that you can run to verify that the function works
test('collections: groupBy with selector', function() {
var list = ["one", "two", "three", "four", "five", "six", "seven", "eight", "nine", "ten"];
var selected = _.groupByAndMap(list, 'length', function(num){ return num.substr(0, 2); });
deepEqual(selected, {
'3': ['on', 'tw', 'si', 'te'],
'4': ['fo', 'fi', 'ni'],
'5': ['th', 'se', 'ei']
});
var lens = _.groupByAndMap(list, function(num){ return num.indexOf('f'); }, 'length');
deepEqual(lens, {
'-1': [3, 3, 5, 3, 5, 5, 4, 3],
'0': [4, 4],
});
});
@gino8080
Copy link

Great!! thank you

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment