I have a javascript array, and I want to get all unique values for a particular key. I have implemented it using underscore like this:
var v = { "b" : 2 };
var w = { "a" : 4, "b" : 2 };
var x = { "a" : 1, "b" : 2 };
var y = { "a" : 4, "b" : 2, "c" : 3 };
var z = { "a" : null, "b" : 2, "c" : 3 };
var data = [v,w,x,y,z];
// this is the part I'd like to make more concise
var keys = _.map(data,function(d) { return d.a; });
keys = _.unique(keys);
keys = _.reject(keys, function(k) { return _.isUndefined(k) || _.isNull(k)});
http://jsfiddle.net/Gc4tJ/
It seems like there should be a more compact way to do this, but I can't quite figure out if there is. I don't need to use underscore here either. I'm using d3 but couldn't quite figure out a simpler way to do this in d3 either.
You could simplify by using the pluck method. Also, the reject thing could be shortened by using either compact or without.
var values = _.chain(data).pluck("a").unique().compact().value();
If you're ok with the a property being cast to a string, you can use d3.set. Without underscore, correctly checking for null and undefined is a little cumbersome, it might make sense to create your own function to do so:
keys = d3.set(
data.map(function(d){ return d.a; })
.filter(function(d){ return (typeof d !== "undefined") ? d !== null : false })
).values();
Just using vanilla javascript is a little longer, but doesn't cast to strings:
keys = data.map(function(d){ return d.a; })
.reduce(function(p, v){ return p.indexOf(v) == -1 ? p.concat(v) : p; }, [])
.filter(function(d){ return (typeof d !== "undefined") ? d !== null : false });
As Bergi points out, you could also use chaining to make your underscore code more concise.
For more underscore/javascript/d3 comparisons, Mike Bostock updated a gist with equivalents between them a few weeks ago. I've added a few more, but they start getting pretty tricky/harder to understand.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With