generated from michael/webpack-base
64 lines
1.5 KiB
TypeScript
64 lines
1.5 KiB
TypeScript
// TODO: remove this, Set is already insertion-ordered in javascript!
|
|
/** an insertion ordered set */
|
|
export default class IOSet<T> {
|
|
// NOTE: this data structure could be improved to have O(1)
|
|
// deletion time if `list` is swapped out with a linked
|
|
// list instead of an array.
|
|
map: Map<T, number>;
|
|
list: T[];
|
|
|
|
constructor(values?: Iterable<T>) {
|
|
this.map = new Map();
|
|
this.list = [];
|
|
|
|
if (values !== undefined) this.extend(values);
|
|
}
|
|
|
|
has(v: T) {
|
|
return this.map.has(v);
|
|
}
|
|
|
|
add(v: T) {
|
|
if (!this.map.has(v)) {
|
|
this.map.set(v, this.list.length);
|
|
this.list.push(v);
|
|
}
|
|
}
|
|
|
|
delete(v: T) {
|
|
const idx = this.map.get(v);
|
|
if (idx === undefined) return false;
|
|
this.map.delete(v);
|
|
this.list.splice(idx, 1);
|
|
return true;
|
|
}
|
|
|
|
extend(values: Iterable<T>) {
|
|
for (const v of values) {
|
|
this.add(v);
|
|
}
|
|
}
|
|
|
|
shift() {
|
|
const v = this.list[0]!;
|
|
// NOTE: performance could be boosted since no need for this.map.get(v) and if
|
|
this.delete(v);
|
|
return v;
|
|
}
|
|
|
|
pop() {
|
|
const v = this.list[this.list.length - 1]!;
|
|
// NOTE: performance could be boosted since no need for this.map.get(v) and if
|
|
this.delete(v);
|
|
return v;
|
|
}
|
|
|
|
get size() {
|
|
return this.list.length;
|
|
}
|
|
|
|
[Symbol.iterator]() {
|
|
return this.list[Symbol.iterator]();
|
|
}
|
|
}
|