/** * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info. * * @author David Sehnal */ interface SetLike { readonly size: number; add(a: T): boolean; has(a: T): boolean; } class HashSetImpl implements SetLike { size: number = 0; private byHash = new Map(); add(a: T) { const hash = this.getHash(a); if (this.byHash.has(hash)) { const xs = this.byHash.get(hash)!; for (let i = 0, _i = xs.length; i < _i; i++) { if (this.areEqual(a, xs[i])) return false; } xs[xs.length] = a; this.size++; return true; } else { this.byHash.set(hash, [a]); this.size++; return true; } } has(v: T) { const hash = this.getHash(v); if (!this.byHash.has(hash)) return false; const xs = this.byHash.get(hash)!; for (let i = 0, _i = xs.length; i < _i; i++) { if (this.areEqual(v, xs[i])) return true; } return false; } constructor(private getHash: (v: T) => any, private areEqual: (a: T, b: T) => boolean) { } } // TODO: add implementations with multilevel hashing support? export function HashSet(getHash: (v: T) => any, areEqual: (a: T, b: T) => boolean): SetLike { return new HashSetImpl(getHash, areEqual); }