Skip to content

Commit 9bb8561

Browse files
committed
Fix d3#2031 - Create a map from an array.
The d3.map constructor can now be used to index the elements of an array by an optional key function, providing a convenient (and faster) alternative to using d3.nest. Before: var objectByKey = d3.nest() .key(function(d) { return d.key; }) .rollup(function(values) { return values[0]; }) .map(objects, d3.map); After: var objectByKey = d3.map(objects, function(d) { return d.key; }); Note that the behavior of the d3.map constructor now changes slightly when a sparse array is used. Previously, missing elements from sparse arrays were skipped by the for-in loop, but now missing elements are indexed.
1 parent 9364923 commit 9bb8561

4 files changed

Lines changed: 37 additions & 10 deletions

File tree

d3.js

Lines changed: 11 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -237,11 +237,18 @@
237237
});
238238
}
239239
}
240-
d3.map = function(object) {
240+
d3.map = function(object, f) {
241241
var map = new d3_Map();
242-
if (object instanceof d3_Map) object.forEach(function(key, value) {
243-
map.set(key, value);
244-
}); else for (var key in object) map.set(key, object[key]);
242+
if (object instanceof d3_Map) {
243+
object.forEach(function(key, value) {
244+
map.set(key, value);
245+
});
246+
} else if (Array.isArray(object)) {
247+
var i = -1, n = object.length, o;
248+
if (arguments.length === 1) while (++i < n) map.set(i, object[i]); else while (++i < n) map.set(f.call(object, o = object[i], i), o);
249+
} else {
250+
for (var key in object) map.set(key, object[key]);
251+
}
245252
return map;
246253
};
247254
function d3_Map() {

d3.min.js

Lines changed: 3 additions & 3 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

src/arrays/map.js

Lines changed: 12 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,18 @@
11
import "../core/class";
22

3-
d3.map = function(object) {
3+
d3.map = function(object, f) {
44
var map = new d3_Map;
5-
if (object instanceof d3_Map) object.forEach(function(key, value) { map.set(key, value); });
6-
else for (var key in object) map.set(key, object[key]);
5+
if (object instanceof d3_Map) {
6+
object.forEach(function(key, value) { map.set(key, value); });
7+
} else if (Array.isArray(object)) {
8+
var i = -1,
9+
n = object.length,
10+
o;
11+
if (arguments.length === 1) while (++i < n) map.set(i, object[i]);
12+
else while (++i < n) map.set(f.call(object, o = object[i], i), o);
13+
} else {
14+
for (var key in object) map.set(key, object[key]);
15+
}
716
return map;
817
};
918

test/arrays/map-test.js

Lines changed: 11 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -49,6 +49,17 @@ suite.addBatch({
4949
assert.equal(b.get("foo"), 42);
5050
a.set("bar", true);
5151
assert.isFalse(b.has("bar"));
52+
},
53+
"map(array) creates a map by index": function(map) {
54+
assert.deepEqual(map(["foo", "bar"]).entries(), [{key: "0", value: "foo"}, {key: "1", value: "bar"}]);
55+
},
56+
"map(array) indexes missing elements in sparse arrays": function(map) {
57+
assert.deepEqual(map(["foo", , "bar"]).entries(), [{key: "0", value: "foo"}, {key: "1", value: undefined}, {key: "2", value: "bar"}]);
58+
},
59+
"map(array, f) creates a map by accessor": function(map) {
60+
assert.deepEqual(map([{field: "foo"}, {field: "bar"}], function(d) { return d.field; }).entries(), [{key: "foo", value: {field: "foo"}}, {key: "bar", value: {field: "bar"}}]);
61+
assert.deepEqual(map([{field: "foo"}, {field: "bar"}], function(d, i) { return i; }).entries(), [{key: "0", value: {field: "foo"}}, {key: "1", value: {field: "bar"}}]);
62+
assert.deepEqual(map([{field: "foo"}, {field: "bar"}], function(d, i) { return this[i].field; }).entries(), [{key: "foo", value: {field: "foo"}}, {key: "bar", value: {field: "bar"}}]);
5263
}
5364
},
5465
"size": {

0 commit comments

Comments
 (0)