HiveBrain v1.2.0
Get Started
← Back to all entries
patternjavascriptMinor

groupBy implementation in NodeJS

Submitted by: @import:stackexchange-codereview··
0
Viewed 0 times
groupbyimplementationnodejs

Problem

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?

Solution

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(item);
    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.

Code Snippets

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(item);
    return memo;
  }, {});
}

Context

StackExchange Code Review Q#66733, answer score: 7

Revisions (0)

No revisions yet.