Take the 2-minute tour ×
Code Review Stack Exchange is a question and answer site for peer programmer code reviews. It's 100% free, no registration required.

I came across a problem in my NodeJS app, which I solved by creating a method called groupBy. The purpose of this method is simple: take an array, and a function which will select a field from an element in the array. Each element in the array should then be grouped based on this field and returned as an object with the key being the value of the field selected.

var groupBy = function(arr, keySelector) {
    var map = {};
    arr.map(function(element) {
        var key = keySelector(element);
        if(key === undefined)
            throw 'undefined key!';

        map[key] = map[key] || [];
        map[key].push(element);
    });
    return map;
};

It works perfectly, but could it be improved in any way?

share|improve this question

1 Answer 1

up vote 2 down vote accepted

Looks OK.

Though I have to ask why you're using map, when you're not really mapping the array to a new array. Using reduce would be more semantically correct, but in this case even just replacing map with forEach would also be more accurate. (The difference is literally only skin-deep; there's zero change in overall functionality.)

I might ask why an undefined value should throw an exception, though. It'll work fine without it, and I might want to group objects based on whether or not they have a certain property or not. Without the exception, I'd be able to get back an object with some of the elements grouped by the key "undefined"

And if I were super nit-picky, I'd say you should always using braces even for one-line "block" like your throw line.

I'm betting, though, that a lot of the time, you'll want to group by a simple, named key, in which case it'd be much easier to pass in a string, rather than a function. A custom function is still very useful, though, so it'd be nice to support both.

I might do:

function groupBy(array, keyOrIterator) {
  var iterator, key;

  // use the function passed in, or create one
  if(typeof key !== 'function') {
    key = String(keyOrIterator);
    iterator = function (item) { return item[key]; };
  } else {
    iterator = keyOrIterator;
  }

  return array.reduce(function (memo, item) {
    var key = iterator(item);
    memo[key] = memo[key] || [];
    memo[key].push(element);
    return memo;
  }, {});
}

Lastly: Libraries like underscore.js and it's "doppelgänger" lo-dash has this and many other helpful functions, ready for you to use. I'm only mentioning it because if you found yourself needed a groupBy function, you'll probably find yourself needing other similar functions, and libraries like those provide that in spades.

share|improve this answer
    
I might ask why an undefined value should throw an exception, though - I don't think an undefined key is suitable in my usecase, although it is good food for thought. The reason why I used a function is simply because I'm spoiled by C#'s GroupBy :). I actually came across lodash after writing this function, but I was interested in feedback all the same. –  Dan Pantry Oct 15 '14 at 12:14
    
I'm glad you referenced underscore and lo-dash -- those are highly used and heavily tested lightweight librarires. If you really wanted a standalone groupby function, why not look at what is already out there (open source)? –  y3sh Oct 15 '14 at 12:56
    
Hindsight is 20/20 - I didn't want to go searching for a library to do this that and the other. I knew what I wanted to achieve and wrote a function for it. I'd heard of lodash but never actually used it before, only saw it in passing on npm dependencies. I wouldn't've known to look for something I didn't know existed after all ;-) –  Dan Pantry Oct 15 '14 at 13:26
    
@DanPantry Hindsight is always 20/20 with such things. I know I've written a lot of code I've later found libraries for. But at least it's always a learning experience in one way or another. Either you learn something just by doing your own implementation, or you learn something from looking at the library's implementation, or you just learn what libraries to look for. Or - once in a blue moon - you learn that your implementation is better, in one way or another, than any of the libraries' :) –  Flambino Oct 15 '14 at 13:33

Your Answer

 
discard

By posting your answer, you agree to the privacy policy and terms of service.

Not the answer you're looking for? Browse other questions tagged or ask your own question.