// TODO: remove this, Set is already insertion-ordered in javascript! /** an insertion ordered set */ export default class IOSet { // 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; list: T[]; constructor(values?: Iterable) { 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) { 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](); } }