mirror of
https://github.com/microsoft/TypeScript.git
synced 2026-05-17 21:06:50 -05:00
Introduce set with custom equals and getHashCode (#48169)
* Implement set with custom equals and getHashCode * Adopt custom set in session * Add doc comment * Initially store buckets as non-arrays
This commit is contained in:
@@ -29,5 +29,167 @@ namespace ts {
|
||||
assert.isTrue(equalOwnProperties({ a: 1 }, { a: 2 }, () => true), "valid equality");
|
||||
});
|
||||
});
|
||||
describe("customSet", () => {
|
||||
it("mutation", () => {
|
||||
const set = createSet<number, number>(x => x % 2, (x, y) => (x % 4) === (y % 4));
|
||||
assert.equal(set.size, 0);
|
||||
|
||||
const newSet = set.add(0);
|
||||
assert.strictEqual(newSet, set);
|
||||
assert.equal(set.size, 1);
|
||||
|
||||
set.add(1);
|
||||
assert.equal(set.size, 2);
|
||||
|
||||
set.add(2); // Collision with 0
|
||||
assert.equal(set.size, 3);
|
||||
|
||||
set.add(3); // Collision with 1
|
||||
assert.equal(set.size, 4);
|
||||
|
||||
set.add(4); // Already present as 0
|
||||
assert.equal(set.size, 4);
|
||||
|
||||
set.add(5); // Already present as 1
|
||||
assert.equal(set.size, 4);
|
||||
|
||||
assert.isTrue(set.has(6));
|
||||
assert.isTrue(set.has(7));
|
||||
|
||||
assert.isTrue(set.delete(8));
|
||||
assert.equal(set.size, 3);
|
||||
assert.isFalse(set.has(8));
|
||||
assert.isFalse(set.delete(8));
|
||||
|
||||
assert.isTrue(set.delete(9));
|
||||
assert.equal(set.size, 2);
|
||||
|
||||
assert.isTrue(set.delete(10));
|
||||
assert.equal(set.size, 1);
|
||||
|
||||
assert.isTrue(set.delete(11));
|
||||
assert.equal(set.size, 0);
|
||||
});
|
||||
it("resizing", () => {
|
||||
const set = createSet<number, number>(x => x % 2, (x, y) => x === y);
|
||||
const elementCount = 100;
|
||||
|
||||
for (let i = 0; i < elementCount; i++) {
|
||||
assert.isFalse(set.has(i));
|
||||
set.add(i);
|
||||
assert.isTrue(set.has(i));
|
||||
assert.equal(set.size, i + 1);
|
||||
}
|
||||
|
||||
for (let i = 0; i < elementCount; i++) {
|
||||
assert.isTrue(set.has(i));
|
||||
set.delete(i);
|
||||
assert.isFalse(set.has(i));
|
||||
assert.equal(set.size, elementCount - (i + 1));
|
||||
}
|
||||
});
|
||||
it("clear", () => {
|
||||
const set = createSet<number, number>(x => x % 2, (x, y) => (x % 4) === (y % 4));
|
||||
for (let j = 0; j < 2; j++) {
|
||||
for (let i = 0; i < 100; i++) {
|
||||
set.add(i);
|
||||
}
|
||||
assert.equal(set.size, 4);
|
||||
|
||||
set.clear();
|
||||
assert.equal(set.size, 0);
|
||||
assert.isFalse(set.has(0));
|
||||
}
|
||||
});
|
||||
it("forEach", () => {
|
||||
const set = createSet<number, number>(x => x % 2, (x, y) => (x % 4) === (y % 4));
|
||||
for (let i = 0; i < 100; i++) {
|
||||
set.add(i);
|
||||
}
|
||||
|
||||
const values: number[] = [];
|
||||
const keys: number[] = [];
|
||||
set.forEach((value, key) => {
|
||||
values.push(value);
|
||||
keys.push(key);
|
||||
});
|
||||
|
||||
assert.equal(values.length, 4);
|
||||
|
||||
values.sort();
|
||||
keys.sort();
|
||||
|
||||
// NB: first equal value wins (i.e. not [96, 97, 98, 99])
|
||||
const expected = [0, 1, 2, 3];
|
||||
assert.deepEqual(values, expected);
|
||||
assert.deepEqual(keys, expected);
|
||||
});
|
||||
it("iteration", () => {
|
||||
const set = createSet<number, number>(x => x % 2, (x, y) => (x % 4) === (y % 4));
|
||||
for (let i = 0; i < 4; i++) {
|
||||
set.add(i);
|
||||
}
|
||||
|
||||
const expected = [0, 1, 2, 3];
|
||||
let actual: number[];
|
||||
|
||||
actual = arrayFrom(set.keys());
|
||||
actual.sort();
|
||||
assert.deepEqual(actual, expected);
|
||||
|
||||
actual = arrayFrom(set.values());
|
||||
actual.sort();
|
||||
assert.deepEqual(actual, expected);
|
||||
|
||||
const actualTuple = arrayFrom(set.entries());
|
||||
assert.isFalse(actualTuple.some(([v, k]) => v !== k));
|
||||
actual = actualTuple.map(([v, _]) => v);
|
||||
actual.sort();
|
||||
assert.deepEqual(actual, expected);
|
||||
});
|
||||
it("string hash code", () => {
|
||||
interface Thing {
|
||||
x: number;
|
||||
y: string;
|
||||
}
|
||||
|
||||
const set = createSet<Thing, string>(t => t.y, (t, u) => t.x === u.x && t.y === u.y);
|
||||
|
||||
const thing1: Thing = {
|
||||
x: 1,
|
||||
y: "a",
|
||||
};
|
||||
|
||||
const thing2: Thing = {
|
||||
x: 2,
|
||||
y: "b",
|
||||
};
|
||||
|
||||
const thing3: Thing = {
|
||||
x: 3,
|
||||
y: "a", // Collides with thing1
|
||||
};
|
||||
|
||||
set.add(thing1);
|
||||
set.add(thing2);
|
||||
set.add(thing3);
|
||||
|
||||
assert.equal(set.size, 3);
|
||||
|
||||
assert.isTrue(set.has(thing1));
|
||||
assert.isTrue(set.has(thing2));
|
||||
assert.isTrue(set.has(thing3));
|
||||
|
||||
assert.isFalse(set.has({
|
||||
x: 4,
|
||||
y: "a", // Collides with thing1
|
||||
}));
|
||||
|
||||
assert.isFalse(set.has({
|
||||
x: 5,
|
||||
y: "c", // No collision
|
||||
}));
|
||||
});
|
||||
});
|
||||
});
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user