array.ts 4.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158
  1. /**
  2. * Copyright (c) 2018-2021 mol* contributors, licensed under MIT, See LICENSE file for more info.
  3. *
  4. * @author Alexander Rose <alexander.rose@weirdbyte.de>
  5. */
  6. import { NumberArray } from './type-helpers';
  7. // TODO move to mol-math as Vector???
  8. /** Get the maximum value in an array */
  9. export function arrayMax(array: ArrayLike<number>) {
  10. let max = -Infinity;
  11. for (let i = 0, il = array.length; i < il; ++i) {
  12. if (array[i] > max) max = array[i];
  13. }
  14. return max;
  15. }
  16. /** Get the minimum value in an array */
  17. export function arrayMin(array: ArrayLike<number>) {
  18. let min = Infinity;
  19. for (let i = 0, il = array.length; i < il; ++i) {
  20. if (array[i] < min) min = array[i];
  21. }
  22. return min;
  23. }
  24. /** Get the minimum & maximum value in an array */
  25. export function arrayMinMax(array: ArrayLike<number>) {
  26. let min = Infinity;
  27. let max = -Infinity;
  28. for (let i = 0, il = array.length; i < il; ++i) {
  29. if (array[i] < min) min = array[i];
  30. if (array[i] > max) max = array[i];
  31. }
  32. return [min, max];
  33. }
  34. /** Get the sum of values in an array */
  35. export function arraySum(array: ArrayLike<number>, stride = 1, offset = 0) {
  36. const n = array.length;
  37. let sum = 0;
  38. for (let i = offset; i < n; i += stride) {
  39. sum += array[i];
  40. }
  41. return sum;
  42. }
  43. /** Get the mean of values in an array */
  44. export function arrayMean(array: ArrayLike<number>, stride = 1, offset = 0) {
  45. return arraySum(array, stride, offset) / (array.length / stride);
  46. }
  47. /** Get the root mean square of values in an array */
  48. export function arrayRms(array: ArrayLike<number>) {
  49. const n = array.length;
  50. let sumSq = 0;
  51. for (let i = 0; i < n; ++i) {
  52. const di = array[i];
  53. sumSq += di * di;
  54. }
  55. return Math.sqrt(sumSq / n);
  56. }
  57. /** Fill an array with serial numbers starting from 0 until n - 1 (defaults to array.length) */
  58. export function fillSerial<T extends NumberArray>(array: T, n?: number) {
  59. for (let i = 0, il = n ? Math.min(n, array.length) : array.length; i < il; ++i) array[i] = i;
  60. return array;
  61. }
  62. export function arrayRemoveInPlace<T>(xs: T[], x: T) {
  63. let i = 0, found = false;
  64. for (const il = xs.length; i < il; i++) {
  65. if (xs[i] === x) {
  66. found = true;
  67. break;
  68. }
  69. }
  70. if (!found) return false;
  71. arrayRemoveAtInPlace(xs, i);
  72. return true;
  73. }
  74. export function arrayRemoveAtInPlace<T>(xs: T[], idx: number) {
  75. for (let i = idx, _i = xs.length - 1; i < _i; i++) {
  76. xs[i] = xs[i + 1];
  77. }
  78. xs.pop();
  79. }
  80. export function arraySetAdd<T>(xs: T[], x: T) {
  81. if (xs.indexOf(x) >= 0) return false;
  82. xs.push(x);
  83. return true;
  84. }
  85. export function arraySetRemove<T>(xs: T[], x: T) {
  86. const idx = xs.indexOf(x);
  87. if (idx < 0) return false;
  88. for (let i = idx, _i = xs.length - 1; i < _i; i++) {
  89. xs[i] = xs[i + 1];
  90. }
  91. xs.pop();
  92. return true;
  93. }
  94. /**
  95. * Caution, O(n^2) complexity. Only use for small input sizes.
  96. * For larger inputs consider using `SortedArray`.
  97. */
  98. export function arrayAreIntersecting<T>(xs: T[], ys: T[]) {
  99. for (let i = 0, il = xs.length; i < il; ++i) {
  100. if (ys.includes(xs[i])) return true;
  101. }
  102. return false;
  103. }
  104. /**
  105. * Caution, O(n^2) complexity. Only use for small input sizes.
  106. * For larger inputs consider using `SortedArray`.
  107. */
  108. export function arrayIntersectionSize<T>(xs: T[], ys: T[]) {
  109. let count = 0;
  110. for (let i = 0, il = xs.length; i < il; ++i) {
  111. if (ys.includes(xs[i])) count += 1;
  112. }
  113. return count;
  114. }
  115. export function arrayEqual<T>(xs?: ArrayLike<T>, ys?: ArrayLike<T>) {
  116. if (!xs || xs.length === 0) return !ys || ys.length === 0;
  117. if (!ys) return false;
  118. const lenX = xs.length;
  119. if (lenX !== ys.length) return false;
  120. for (let i = 0; i < lenX; i++) {
  121. if (xs[i] !== ys[i]) return false;
  122. }
  123. return true;
  124. }
  125. export function arrayIsIdentity(xs: ArrayLike<number>) {
  126. for (let i = 0, _i = xs.length; i < _i; i++) {
  127. if (xs[i] !== i) return false;
  128. }
  129. return true;
  130. }
  131. export function arrayMapUpsert<T>(xs: [string, T][], key: string, value: T) {
  132. for (let i = 0, il = xs.length; i < il; ++i) {
  133. if (xs[i][0] === key) {
  134. xs[i][1] = value;
  135. return;
  136. }
  137. }
  138. xs.push([key, value]);
  139. }