array.ts raw

   1  /* eslint-disable @typescript-eslint/no-explicit-any */
   2  declare global {
   3    interface Array<T> {
   4      /**
   5       * Sorts the array by the provided property and returns a new sorted array.
   6       * Default sorting is ASC. You can apply DESC sorting by using the optional parameter "order = 'desc'"
   7       */
   8      sortBy<K>(keyFunction: (t: T) => K, order?: 'asc' | 'desc'): T[];
   9  
  10      /** Check if the array is empty. */
  11      empty(): boolean;
  12  
  13      groupBy<K, R>(
  14        keyFunction: (t: T) => K,
  15        reduceFn: (items: T[]) => R
  16      ): Map<K, R>;
  17    }
  18  }
  19  
  20  if (!Array.prototype.empty) {
  21    Array.prototype.empty = function (): boolean {
  22      return this.length === 0;
  23    };
  24  }
  25  
  26  if (!Array.prototype.sortBy) {
  27    Array.prototype.sortBy = function <T, K>(
  28      keyFunction: (t: T) => K,
  29      order?: string
  30    ): T[] {
  31      if (this.length === 0) {
  32        return [];
  33      }
  34  
  35      // determine sort order (asc or desc / asc is default)
  36      let asc = true;
  37      if (order === 'desc') {
  38        asc = false;
  39      }
  40  
  41      const arrayClone = Array.from(this) as any[];
  42      const firstSortProperty = keyFunction(arrayClone[0]);
  43  
  44      if (typeof firstSortProperty === 'string') {
  45        // string in-place sort
  46        arrayClone.sort((a, b) => {
  47          if (asc) {
  48            return ('' + (keyFunction(a) as unknown as string)).localeCompare(
  49              keyFunction(b) as unknown as string
  50            );
  51          }
  52  
  53          return ('' + (keyFunction(b) as unknown as string)).localeCompare(
  54            keyFunction(a) as unknown as string
  55          );
  56        });
  57      } else if (typeof firstSortProperty === 'number') {
  58        // number in-place sort
  59        if (asc) {
  60          arrayClone.sort(
  61            (a, b) => Number(keyFunction(a)) - Number(keyFunction(b))
  62          );
  63        } else {
  64          arrayClone.sort(
  65            (a, b) => Number(keyFunction(b)) - Number(keyFunction(a))
  66          );
  67        }
  68      } else {
  69        throw new Error('sortBy is not implemented for that type!');
  70      }
  71  
  72      return arrayClone;
  73    };
  74  }
  75  
  76  if (!Array.prototype.groupBy) {
  77    Array.prototype.groupBy = function <T>(
  78      fn: (item: T) => any,
  79      reduceFn: (items: T[]) => any
  80    ): Map<any, any> {
  81      const result = new Map<any, any>();
  82  
  83      const distinctKeys = new Set<any>(this.map((x) => fn(x)));
  84  
  85      for (const distinctKey of distinctKeys) {
  86        const distinctKeyItems = this.filter((x) => fn(x) === distinctKey);
  87  
  88        result.set(distinctKey, reduceFn(distinctKeyItems));
  89      }
  90  
  91      return result;
  92    };
  93  }
  94  
  95  export {};
  96