hash-set.ts 1.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051
  1. /**
  2. * Copyright (c) 2017 molio 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: { [hash: number]: T[] } = Object.create(null);
  14. add(a: T) {
  15. const hash = this.getHash(a);
  16. if (this.byHash[hash]) {
  17. const xs = this.byHash[hash];
  18. for (const x of xs) {
  19. if (this.areEqual(a, x)) return false;
  20. }
  21. xs[xs.length] = a;
  22. this.size++;
  23. return true;
  24. } else {
  25. this.byHash[hash] = [a];
  26. this.size++;
  27. return true;
  28. }
  29. }
  30. has(v: T) {
  31. const hash = this.getHash(v);
  32. if (!this.byHash[hash]) return false;
  33. for (const x of this.byHash[hash]) {
  34. if (this.areEqual(v, x)) return true;
  35. }
  36. return false;
  37. }
  38. constructor(private getHash: (v: T) => any, private areEqual: (a: T, b: T) => boolean) { }
  39. }
  40. // TODO: add implementations with multilevel hashing support?
  41. function HashSet<T>(getHash: (v: T) => any, areEqual: (a: T, b: T) => boolean): SetLike<T> {
  42. return new HashSetImpl<T>(getHash, areEqual);
  43. }
  44. export default HashSet;