array.ts 1.5 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950
  1. import { randRange } from "./math";
  2. /** Describes an array with at least one item */
  3. export type NonEmptyArray<T = unknown> = [T, ...T[]];
  4. /** Returns a random item from the passed array */
  5. export function randomItem<T = unknown>(array: T[]) {
  6. return randomItemIndex<T>(array)[0];
  7. }
  8. /**
  9. * Returns a tuple of a random item and its index from the passed array
  10. * Returns `[undefined, undefined]` if the passed array is empty
  11. */
  12. export function randomItemIndex<T = unknown>(array: T[]): [item?: T, index?: number] {
  13. if(array.length === 0)
  14. return [undefined, undefined];
  15. const idx = randRange(array.length - 1);
  16. return [array[idx]!, idx];
  17. }
  18. /** Returns a random item from the passed array and mutates the array to remove the item */
  19. export function takeRandomItem<T = unknown>(arr: T[]) {
  20. const [itm, idx] = randomItemIndex<T>(arr);
  21. if(idx === undefined)
  22. return undefined;
  23. arr.splice(idx, 1);
  24. return itm as T;
  25. }
  26. /** Returns a copy of the array with its items in a random order */
  27. export function randomizeArray<T = unknown>(array: T[]) {
  28. const retArray = [...array]; // so array and retArray don't point to the same memory address
  29. if(array.length === 0)
  30. return array;
  31. // shamelessly stolen from https://javascript.info/task/shuffle
  32. for(let i = retArray.length - 1; i > 0; i--) {
  33. const j = Math.floor((randRange(0, 10000) / 10000) * (i + 1));
  34. // @ts-ignore
  35. [retArray[i], retArray[j]] = [retArray[j], retArray[i]];
  36. }
  37. return retArray;
  38. }