UNPKG

voided-data

Version:

Proper DS for TS

97 lines (96 loc) 3.53 kB
"use strict"; var __importDefault = (this && this.__importDefault) || function (mod) { return (mod && mod.__esModule) ? mod : { "default": mod }; }; Object.defineProperty(exports, "__esModule", { value: true }); exports.createHashTable = void 0; const maybe_1 = require("../../monads/maybe"); const hash_1 = __importDefault(require("../../objects/hash")); const equals_1 = __importDefault(require("../../objects/equals")); const MIN_LOAD = 0.25; const MAX_LOAD = 1; const EXPANSION_FACTOR = 2; const CONTRACTION_FACTOR = 0.5; const MIN_CAPACITY = 32; function createHashTable() { let size = 0; let capacity = MIN_CAPACITY; let buckets = new Array(capacity).fill(null).map(() => []); const iter = () => buckets.flatMap((bucket) => bucket.map(([k, v]) => [k, v])); const load = () => size / capacity; const _set = (key, value) => { const _hash = (0, hash_1.default)(key) % capacity; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const _bucket = buckets[_hash]; const pair = _bucket.find(([k]) => (0, equals_1.default)(k, key)); if (!pair) { _bucket.push([key, value]); return true; } pair[1] = value; return false; }; const resize = () => { const _load = load(); let newCapacity = capacity; if (_load < MIN_LOAD) { newCapacity = Math.max(capacity * CONTRACTION_FACTOR, MIN_CAPACITY); } if (_load > MAX_LOAD) { newCapacity = capacity * EXPANSION_FACTOR; } if (newCapacity !== capacity) { capacity = newCapacity; const oldBuckets = buckets; buckets = new Array(capacity).fill(null).map(() => []); oldBuckets.forEach((bucket) => bucket.forEach(([k, v]) => _set(k, v))); } }; return { size: () => size, set(key, value) { if (_set(key, value)) { size++; resize(); } }, iter, get(key) { const _hash = (0, hash_1.default)(key) % capacity; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const _bucket = buckets[_hash]; const pair = _bucket.find(([k]) => (0, equals_1.default)(k, key)); if (!pair) { return (0, maybe_1.none)(); } return (0, maybe_1.some)(pair[1]); }, unset(key) { const _hash = (0, hash_1.default)(key) % capacity; // eslint-disable-next-line @typescript-eslint/no-non-null-assertion const _bucket = buckets[_hash]; const _newBucket = _bucket.filter(([k]) => !(0, equals_1.default)(k, key)); buckets[_hash] = _newBucket; if (_newBucket.length !== _bucket.length) { size--; resize(); } }, map(mapper) { const newMap = createHashTable(); iter().forEach((pair) => { const [nk, nv] = mapper(pair); newMap.set(nk, nv); }); return newMap; }, toString() { return ('{ ' + iter() .map((pair) => JSON.stringify(pair)) .join(',') + ' }'); }, }; } exports.createHashTable = createHashTable;