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.

My objective is to make an array of unique keys from a list of objects.

Example:

Input:

var input = [{"a":1, "b":2}, {"a":3, "c":4}, {"a":5}]

Output:

[ "a", "b", "c" ]

Current approach:

var outputObj={};
input.map( function( obj ) {  
    Object.keys( obj ).map( function(key) { 
        outputObj[key] = 1;
    })  
});
// output obj is now { a : 1, b: 1, c: 1 }
var output = Object.keys( outputObj );

This works, but it just smells funny, partly because the map function is relying on side-effects. Is there a better way to do this?

In Java, I would create a java.util.Set and simply add all keys to it.

share|improve this question

1 Answer 1

up vote 5 down vote accepted

You could clean it up a bit by using reduce and forEach instead of map (especially as you don't need map's return value, but are just using it as an iterator)

function uniqueKeys(objects) {
  var keys = objects.reduce(function (collector, obj) {
    Object.keys(obj).forEach(function (key) {
      collector[key] = true;
    });
    return collector;
  }, {});
  return Object.keys(keys);
}

Alternatively, you could combine all the objects, and then use Object.keys on the result. Just be careful, as extend-type functions usually work on the passed objects directly (as the one below does), rather than returning a new object, so pass an empty object to use as collector:

function extend(target, source) {
  var key;
  for(key in source) {
    target[key] = source[key];
  }
  return target;
}

function uniqueKeys(objects) {
  var combined = objects.reduce(function (target, obj) {
    extend(target, obj);
    return target;
  }, {});
  return Object.keys(combined);
}

If you've got an extend function that takes an arbitrary number of arguments, you could do something like

function uniqueKeys(objects) {
  var collector = {};
  extend.apply(null, [collector].concat(objects));
  return Object.keys(collector);
}

Here are demos of each one

share|improve this answer

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.