hash-set.ts 1.4 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. /**
  2. * Copyright (c) 2017 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author David Sehnal <david.sehnal@gmail.com>
  5. */
  6. interface SetLike<T> {
  7. readonly size: number;
  8. add(a: T): boolean;
  9. has(a: T): boolean;
  10. }
  11. class HashSetImpl<T> implements SetLike<T> {
  12. size: number = 0;
  13. private byHash = new Map<number, T[]>();
  14. add(a: T) {
  15. const hash = this.getHash(a);
  16. if (this.byHash.has(hash)) {
  17. const xs = this.byHash.get(hash)!;
  18. for (let i = 0, _i = xs.length; i < _i; i++) {
  19. if (this.areEqual(a, xs[i])) return false;
  20. }
  21. xs[xs.length] = a;
  22. this.size++;
  23. return true;
  24. } else {
  25. this.byHash.set(hash, [a]);
  26. this.size++;
  27. return true;
  28. }
  29. }
  30. has(v: T) {
  31. const hash = this.getHash(v);
  32. if (!this.byHash.has(hash)) return false;
  33. const xs = this.byHash.get(hash)!;
  34. for (let i = 0, _i = xs.length; i < _i; i++) {
  35. if (this.areEqual(v, xs[i])) return true;
  36. }
  37. return false;
  38. }
  39. constructor(private getHash: (v: T) => any, private areEqual: (a: T, b: T) => boolean) { }
  40. }
  41. // TODO: add implementations with multilevel hashing support?
  42. export function HashSet<T>(getHash: (v: T) => any, areEqual: (a: T, b: T) => boolean): SetLike<T> {
  43. return new HashSetImpl<T>(getHash, areEqual);
  44. }