Underscore example:
_.each([1, 2, 3], function(num) { alert(num); });
Vanilla equivalent:
[1, 2, 3].forEach(function(num) { alert(num); });
Underscore example:
_.each({one: 1, two: 2, three: 3}, function(num, key) { alert(num); });
D3 equivalent using d3.values (d3.entries and d3.map forEach would also work):
d3.values({one: 1, two: 2, three: 3}).forEach(function(num) { alert(num); });
Underscore example:
_.map([1, 2, 3], function(num) { return num * 3; });
Vanilla equivalent:
[1, 2, 3].map(function(num) { return num * 3; });
Underscore example:
_.map({one: 1, two: 2, three: 3}, function(num, key) { return num * 3; });
D3 equivalent with d3.values (d3.entries and d3.map values.map would also work):
d3.values({one: 1, two: 2, three: 3}).map(function(num) { return num * 3; });
Underscore example:
var sum = _.reduce([1, 2, 3], function(memo, num) { return memo + num; }, 0);
Vanilla equivalent:
var sum = [1, 2, 3].reduce(function(memo, num) { return memo + num; }, 0);
Given:
var list = [[0, 1], [2, 3], [4, 5]];
Underscore example:
var flat = _.reduceRight(list, function(a, b) { return a.concat(b); }, []);
Vanilla equivalent:
var flat = list.reduceRight(function(a, b) { return a.concat(b); }, []);
Underscore example:
var even = _.find([1, 2, 3, 4, 5, 6], function(num) { return num % 2 == 0; });
There’s no proper Vanilla equivalent of Underscore’s find method, but you can approximate it with array.filter. This is typically slower because it doesn’t stop once the first match is found:
var even = [1, 2, 3, 4, 5, 6].filter(function(num) { return num % 2 == 0; })[0];
A closer approximate is array.some, but this is less convenient because it requires the closure to set an enclosing variable:
var even; [1, 2, 3, 4, 5, 6].some(function(num) { return num % 2 == 0 && (even = num, true); });
Underscore example:
_.contains([1, 2, 3], 3);
Vanilla equivalent:
[1, 2, 3].indexOf(3) >= 0;
Underscore example:
_.invoke([[5, 1, 7], [3, 2, 1]], "sort"]);
Vanilla equivalent:
[[5, 1, 7], [3, 2, 1]].forEach(function(array) { array.sort(); });
Note: JavaScript’s built-in array.sort sorts lexicographically rather than numerically; you almost always want to say array.sort(d3.ascending)
, or array.sort(function(a, b) { return a - b; })
if you know you’re sorting numbers or dates.
Given:
var stooges = [{name: "moe", age: 40}, {name: "larry", age: 50}, {name: "curly", age: 60}];
Underscore example:
_.pluck(stooges, "name");
Vanilla equivalent:
stooges.map(function(stooge) { return stooge.name; });
Given:
var stooges = [{name: "moe", age: 40}, {name: "larry", age: 50}, {name: "curly", age: 60}];
Underscore example:
_.max(stooges, function(stooge) { return stooge.age; });
Vanilla equivalent. You can omit the null argument if you know that stooges is non-empty or you’d prefer a TypeError:
stooges.reduce(function(p, v) { return v.age > p.age ? v : p; }, null);
Using d3.max is not exactly equivalent because it returns the maximum value, rather than the corresponding object. Also, d3.max ignores null, undefined and NaN values. Often, this is what you want:
d3.max(stooges, function(stooge) { return stooge.age; });
Given:
var numbers = [10, 5, 100, 2, 1000];
Underscore example:
_.min(numbers);
Vanilla equivalent:
numbers.reduce(function(p, v) { return Math.min(p, v); }, Infinity);
Using d3.min (not equivalent; see above regarding d3.max):
d3.min(numbers);
Underscore example:
_.sortBy([1, 2, 3, 4, 5, 6], function(num) { return Math.sin(num); });
Vanilla equivalent:
[1, 2, 3, 4, 5, 6].sort(function(a, b) { return Math.sin(a) - Math.sin(b); });
In the vanilla equivalent, the comparator is invoked once per comparison rather than once per element; thus the vanilla version is potentially slower. More critically, array.sort doesn’t support nondeterministic comparators. You could fix that with a temporary array holding the mapped values, a second temporary array holding the indexes, and d3.permute:
var array = [1, 2, 3, 4, 5, 6], sin = array.map(Math.sin);
d3.permute(array, d3.range(array.length).sort(function(i, j) { return sin[i] - sin[j]; }));
Underscore example:
_.groupBy([1.3, 2.1, 2.4], function(num){ return Math.floor(num); });
D3 equivalent:
d3.nest().key(Math.floor).map([1.3, 2.1, 2.4]);
Underscore example:
_.groupBy(["one", "two", "three"], "length");
D3 equivalent:
d3.nest().key(function(d) { return d.length; }).map(["one", "two", "three"]);
D3’s nest operator supports more than one level of grouping, and can also return nested entries that preserve order.
Underscore example:
_.countBy([1, 2, 3, 4, 5], function(num) {
return num % 2 == 0 ? "even" : "odd";
});
D3 equivalent using nest.rollup:
d3.nest()
.key(function(num) { return num % 2 == 0 ? "even" : "odd"; })
.rollup(function(values) { return values.length; })
.map([1, 2, 3, 4, 5]);
Underscore example:
_.shuffle([1, 2, 3, 4, 5, 6]);
D3 equivalent:
d3.shuffle([1, 2, 3, 4, 5, 6]);
Underscore example:
(function(){ return _.toArray(arguments).slice(1); })(1, 2, 3, 4);
Vanilla equivalent:
(function(){ return [].slice.call(arguments, 1); })(1, 2, 3, 4);
Underscore example:
_.size({one: 1, two: 2, three: 3});
Vanilla equivalent using Object.keys:
Object.keys({one: 1, two: 2, three: 3}).length;
D3 equivalent using d3.keys:
d3.keys({one: 1, two: 2, three: 3}).length;
D3 equivalent using d3.map, if you want to perform other operations:
d3.map({one: 1, two: 2, three: 3}).keys().length;
Given:
var numbers = [5, 4, 3, 2, 1];
Underscore example:
_.first(numbers);
Vanilla equivalent when no n is specified:
numbers[0];
Vanilla equivalent when n is specified:
numbers.slice(0, n);
Given:
var numbers = [5, 4, 3, 2, 1];
Underscore example:
_.initial(numbers);
Vanilla equivalent when no n is specified:
numbers.slice(0, numbers.length - 1);
Vanilla equivalent when n is specified:
numbers.slice(0, numbers.length - n);
Given:
var numbers = [5, 4, 3, 2, 1];
Underscore example:
_.last(numbers);
Vanilla equivalent when no n is specified:
numbers[numbers.length - 1];
Vanilla equivalent when n is specified:
numbers.slice(numbers.length - n);
Given:
var numbers = [5, 4, 3, 2, 1];
Underscore example:
_.rect(numbers);
Vanilla equivalent when no n is specified:
numbers.slice(1);
Vanilla equivalent when n is specified:
numbers.slice(n);
Underscore example:
_.compact([0, 1, false, 2, '', 3]);
Vanilla equivalent:
[0, 1, false, 2, '', 3].filter(function(d) { return d; });
TODO …
_.flatten([1, [2], [3, [[4]]]]);
_.flatten([1, [2], [3, [[4]]]], true);
TODO …
_.without([1, 2, 1, 0, 3, 1, 4], 0, 1);
TODO …
_.union([1, 2, 3], [101, 2, 1, 10], [2, 1]);
TODO …
_.intersection([1, 2, 3], [101, 2, 1, 10], [2, 1]);
TODO …
_.difference([1, 2, 3, 4, 5], [5, 2, 10]);
Underscore example:
_.uniq([1, 2, 1, 3, 1, 4]);
D3 equivalent for strings:
d3.set(["1", "2", "1", "3", "1", "4"]).values();
TODO equivalent for non-string values
Underscore example:
_.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
D3 equivalent:
d3.zip(['moe', 'larry', 'curly'], [30, 40, 50], [true, false, false]);
TODO …
_.object(['moe', 'larry', 'curly'], [30, 40, 50]);
TODO … Vanilla array.indexOf
TODO … Vanilla array.lastIndexOf
TODO … d3.bisect
Underscore example:
_.range(10);
_.range(1, 11);
_.range(0, 30, 5);
_.range(0, -10, -1);
_.range(0);
D3 equivalent:
d3.range(10);
d3.range(1, 11);
d3.range(0, 30, 5);
d3.range(0, -10, -1);
d3.range(0);
…