Skip to content

Commit 120ad7a

Browse files
Filmbostock
andauthoredJun 5, 2021
adopt InternMap for ordinal scales (#237)
* adopt InternMap for ordinal scales * optimize * order imports Co-authored-by: Mike Bostock <mbostock@gmail.com>
1 parent ac30873 commit 120ad7a

File tree

4 files changed

+49
-21
lines changed

4 files changed

+49
-21
lines changed
 

‎package.json

+1-1
Original file line numberDiff line numberDiff line change
@@ -33,7 +33,7 @@
3333
},
3434
"sideEffects": false,
3535
"dependencies": {
36-
"d3-array": "2.3.0 - 3",
36+
"d3-array": "2.10.0 - 3",
3737
"d3-format": "1 - 3",
3838
"d3-interpolate": "1.2.0 - 3",
3939
"d3-time": "2.1.1 - 3",

‎src/ordinal.js

+9-9
Original file line numberDiff line numberDiff line change
@@ -1,29 +1,29 @@
1+
import {InternMap} from "d3-array";
12
import {initRange} from "./init.js";
23

34
export const implicit = Symbol("implicit");
45

56
export default function ordinal() {
6-
var index = new Map(),
7+
var index = new InternMap(),
78
domain = [],
89
range = [],
910
unknown = implicit;
1011

1112
function scale(d) {
12-
var key = d + "", i = index.get(key);
13-
if (!i) {
13+
let i = index.get(d);
14+
if (i === undefined) {
1415
if (unknown !== implicit) return unknown;
15-
index.set(key, i = domain.push(d));
16+
index.set(d, i = domain.push(d) - 1);
1617
}
17-
return range[(i - 1) % range.length];
18+
return range[i % range.length];
1819
}
1920

2021
scale.domain = function(_) {
2122
if (!arguments.length) return domain.slice();
22-
domain = [], index = new Map();
23+
domain = [], index = new InternMap();
2324
for (const value of _) {
24-
const key = value + "";
25-
if (index.has(key)) continue;
26-
index.set(key, domain.push(value));
25+
if (index.has(value)) continue;
26+
index.set(value, domain.push(value) - 1);
2727
}
2828
return scale;
2929
};

‎test/ordinal-test.js

+38-10
Original file line numberDiff line numberDiff line change
@@ -11,16 +11,16 @@ it("scaleOrdinal() has the expected defaults", () => {
1111
});
1212

1313
it("ordinal(x) maps a unique name x in the domain to the corresponding value y in the range", () => {
14-
const s = scaleOrdinal().domain([0, 1]).range(["foo", "bar"]);
14+
const s = scaleOrdinal().domain([0, 1]).range(["foo", "bar"]).unknown(undefined);
1515
assert.strictEqual(s(0), "foo");
1616
assert.strictEqual(s(1), "bar");
1717
s.range(["a", "b", "c"]);
1818
assert.strictEqual(s(0), "a");
19-
assert.strictEqual(s("0"), "a");
20-
assert.strictEqual(s([0]), "a");
19+
assert.strictEqual(s("0"), undefined);
20+
assert.strictEqual(s([0]), undefined);
2121
assert.strictEqual(s(1), "b");
22-
assert.strictEqual(s(2.0), "c");
23-
assert.strictEqual(s(new Number(2)), "c");
22+
assert.strictEqual(s(new Number(1)), "b");
23+
assert.strictEqual(s(2), undefined);
2424
});
2525

2626
it("ordinal(x) implicitly extends the domain when a range is explicitly specified", () => {
@@ -59,16 +59,16 @@ it("ordinal.domain() replaces previous domain values", () => {
5959
assert.strictEqual(s(0), "bar");
6060
assert.deepStrictEqual(s.domain(), [1, 0]);
6161
s.domain(["0", "1"]);
62-
assert.strictEqual(s(0), "foo"); // it changed!
63-
assert.strictEqual(s(1), "bar");
62+
assert.strictEqual(s("0"), "foo"); // it changed!
63+
assert.strictEqual(s("1"), "bar");
6464
assert.deepStrictEqual(s.domain(), ["0", "1"]);
6565
});
6666

67-
it("ordinal.domain() uniqueness is based on string coercion", () => {
67+
it("ordinal.domain() uniqueness is based on primitive coercion", () => {
6868
const s = scaleOrdinal().domain(["foo"]).range([42, 43, 44]);
6969
assert.strictEqual(s(new String("foo")), 42);
70-
assert.strictEqual(s({toString: function() { return "foo"; }}), 42);
71-
assert.strictEqual(s({toString: function() { return "bar"; }}), 43);
70+
assert.strictEqual(s({valueOf: function() { return "foo"; }}), 42);
71+
assert.strictEqual(s({valueOf: function() { return "bar"; }}), 43);
7272
});
7373

7474
it("ordinal.domain() does not coerce domain values to strings", () => {
@@ -85,6 +85,34 @@ it("ordinal.domain() does not barf on object built-ins", () => {
8585
assert.deepStrictEqual(s.domain(), ["__proto__", "hasOwnProperty"]);
8686
});
8787

88+
it("ordinal() accepts dates", () => {
89+
const s = scaleOrdinal();
90+
s(new Date(1970, 2, 1));
91+
s(new Date(2001, 4, 13));
92+
s(new Date(1970, 2, 1));
93+
s(new Date(2001, 4, 13));
94+
assert.deepStrictEqual(s.domain(), [new Date(1970, 2, 1), new Date(2001, 4, 13)]);
95+
});
96+
97+
it("ordinal.domain() accepts dates", () => {
98+
const s = scaleOrdinal().domain([
99+
new Date(1970, 2, 1),
100+
new Date(2001, 4, 13),
101+
new Date(1970, 2, 1),
102+
new Date(2001, 4, 13)
103+
]);
104+
s(new Date(1970, 2, 1));
105+
s(new Date(1999, 11, 31));
106+
assert.deepStrictEqual(s.domain(), [new Date(1970, 2, 1), new Date(2001, 4, 13), new Date(1999, 11, 31)]);
107+
});
108+
109+
it("ordinal.domain() does not barf on object built-ins", () => {
110+
const s = scaleOrdinal().domain(["__proto__", "hasOwnProperty"]).range([42, 43]);
111+
assert.strictEqual(s("__proto__"), 42);
112+
assert.strictEqual(s("hasOwnProperty"), 43);
113+
assert.deepStrictEqual(s.domain(), ["__proto__", "hasOwnProperty"]);
114+
});
115+
88116
it("ordinal.domain() is ordered by appearance", () => {
89117
const s = scaleOrdinal();
90118
s("foo");

‎yarn.lock

+1-1
Original file line numberDiff line numberDiff line change
@@ -268,7 +268,7 @@ cross-spawn@^7.0.2:
268268
shebang-command "^2.0.0"
269269
which "^2.0.1"
270270

271-
"d3-array@2 - 3", "d3-array@2.3.0 - 3":
271+
"d3-array@2 - 3", "d3-array@2.10.0 - 3":
272272
version "3.0.1"
273273
resolved "https://registry.yarnpkg.com/d3-array/-/d3-array-3.0.1.tgz#ca45c263f5bb780ab5a34a6e1d3d5883fe4a8d14"
274274
integrity sha512-l3Bh5o8RSoC3SBm5ix6ogaFW+J6rOUm42yOtZ2sQPCEvCqUMepeX7zgrlLLGIemxgOyo9s2CsWEidnLv5PwwRw==

0 commit comments

Comments
 (0)
Please sign in to comment.