[1, 2, 3].forEach(function(num) { alert(num); });
d3.values({one: 1, two: 2, three: 3}).forEach(function(num) { alert(num); });
[1, 2, 3].map(function(num) { return num * 3; });
d3.values({one: 1, two: 2, three: 3}).map(function(num) { return num * 3; });
var sum = [1, 2, 3].reduce(function(memo, num) { return memo + num; }, 0);
Given:
var list = [[0, 1], [2, 3], [4, 5]];
var flat = list.reduceRight(function(a, b) { return a.concat(b); }, []);
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); });
Vanilla equivalent:
[1, 2, 3].indexOf(3) >= 0;
[[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}];
stooges.map(function(stooge) { return stooge.name; });
Given:
var stooges = [{name: "moe", age: 40}, {name: "larry", age: 50}, {name: "curly", age: 60}];
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];
numbers.reduce(function(p, v) { return Math.min(p, v); }, Infinity);
Using d3.min (not equivalent; see above regarding d3.max):
d3.min(numbers);
[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];
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];
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];
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];
Vanilla equivalent when no n is specified:
numbers.slice(1);
Vanilla equivalent when n is specified:
numbers.slice(n);
[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);
…