# Finding unique values in an array

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.

-

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

-