grouping.ts 1.2 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647
  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. export interface Grouping<V, K> {
  7. keys: ReadonlyArray<K>,
  8. groups: ReadonlyArray<ReadonlyArray<V>>
  9. }
  10. class GroupingImpl<K, V> {
  11. private byKey = new Map<K, V[]>();
  12. readonly keys: K[] = [];
  13. readonly groups: V[][] = [];
  14. add(a: V) {
  15. const key = this.getKey(a) as any;
  16. if (!!this.byKey.has(key)) {
  17. const group = this.byKey.get(key)!;
  18. group[group.length] = a;
  19. } else {
  20. const group = [a];
  21. this.byKey.set(key, group);
  22. this.keys[this.keys.length] = key;
  23. this.groups[this.groups.length] = group;
  24. }
  25. }
  26. getGrouping(): Grouping<V, K> {
  27. return { keys: this.keys, groups: this.groups };
  28. }
  29. constructor(private getKey: (v: V) => K) { }
  30. }
  31. export function Grouper<V, K>(getKey: (x: V) => K) {
  32. return new GroupingImpl<K, V>(getKey);
  33. }
  34. function groupBy<V, K>(values: ArrayLike<V>, getKey: (x: V) => K) {
  35. const gs = Grouper(getKey);
  36. for (let i = 0, _i = values.length; i < _i; i++) gs.add(values[i]);
  37. return gs.getGrouping();
  38. }
  39. export default groupBy;