ArrayUtils.ts 3.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137
  1. import { inject, injectable } from 'inversify';
  2. import { ServiceIdentifiers } from '../container/ServiceIdentifiers';
  3. import { IArrayUtils } from '../interfaces/utils/IArrayUtils';
  4. import { IRandomGenerator } from '../interfaces/utils/IRandomGenerator';
  5. @injectable()
  6. export class ArrayUtils implements IArrayUtils {
  7. /**
  8. * @type {IRandomGenerator}
  9. */
  10. private readonly randomGenerator: IRandomGenerator;
  11. /**
  12. * @param {IRandomGenerator} randomGenerator
  13. */
  14. public constructor (
  15. @inject(ServiceIdentifiers.IRandomGenerator) randomGenerator: IRandomGenerator
  16. ) {
  17. this.randomGenerator = randomGenerator;
  18. }
  19. /**
  20. * @param {number} length
  21. * @returns {number[]}
  22. */
  23. public createWithRange (length: number): number[] {
  24. const range: number[] = [];
  25. for (let i: number = 0; i < length; i++) {
  26. range.push(i);
  27. }
  28. return range;
  29. }
  30. /**
  31. * @param {number} length
  32. * @param {(index: number) => TValue} valueFunction
  33. * @returns {TValue[]}
  34. */
  35. public fillWithRange <TValue> (length: number, valueFunction: (index: number) => TValue): TValue[] {
  36. const range: TValue[] = [];
  37. for (let i: number = 0; i < length; i++) {
  38. range.push(valueFunction(i));
  39. }
  40. return range;
  41. }
  42. /**
  43. * @param {T[]} array
  44. * @returns {T | null}
  45. */
  46. public findMostOccurringElement <T extends string | number> (array: T[]): T | null {
  47. const arrayLength: number = array.length;
  48. if (!arrayLength) {
  49. return null;
  50. }
  51. const elementsMap: Partial<{[key in T]: number}> = {};
  52. let mostOccurringElement: T = array[0];
  53. let mostOccurringElementCount: number = 1;
  54. for (const element of array) {
  55. const currentElementCount: number = elementsMap[element] ?? 0;
  56. const updatedElementCount: number = currentElementCount + 1;
  57. if (updatedElementCount > mostOccurringElementCount) {
  58. mostOccurringElement = element;
  59. mostOccurringElementCount = updatedElementCount;
  60. }
  61. elementsMap[element] = updatedElementCount;
  62. }
  63. return mostOccurringElement;
  64. }
  65. /**
  66. * @param {T[]} array
  67. * @returns {T | undefined}
  68. */
  69. public getLastElement <T> (array: T[]): T | undefined {
  70. const arrayLength: number = array.length;
  71. return array[arrayLength - 1] ?? undefined;
  72. }
  73. /**
  74. * @param {T[]} array
  75. * @param {number} times
  76. * @returns {T[]}
  77. */
  78. public rotate <T> (array: T[], times: number): T[] {
  79. if (!array.length) {
  80. throw new ReferenceError('Cannot rotate empty array.');
  81. }
  82. if (times <= 0) {
  83. return array;
  84. }
  85. const newArray: T[] = array;
  86. let temp: T | undefined;
  87. while (times--) {
  88. temp = newArray.pop();
  89. if (temp) {
  90. newArray.unshift(temp);
  91. }
  92. }
  93. return newArray;
  94. }
  95. /**
  96. * @param {T[]} array
  97. * @returns {T[]}
  98. */
  99. public shuffle <T> (array: T[]): T[] {
  100. const shuffledArray: T[] = [...array];
  101. for (let i: number = shuffledArray.length; i; i--) {
  102. const j: number = Math.floor(this.randomGenerator.getMathRandom() * i);
  103. [shuffledArray[i - 1], shuffledArray[j]] = [shuffledArray[j], shuffledArray[i - 1]];
  104. }
  105. return shuffledArray;
  106. }
  107. }