xref: /expo/packages/@expo/cli/src/utils/array.ts (revision 8a424beb)
1/** Returns the last index of an item based on a given criteria. */
2export function findLastIndex<T>(array: T[], predicate: (item: T) => boolean) {
3  for (let i = array.length - 1; i >= 0; i--) {
4    if (predicate(array[i])) {
5      return i;
6    }
7  }
8  return -1;
9}
10
11/** Returns a list of items that intersect between two given arrays. */
12export function intersecting<T>(a: T[], b: T[]): T[] {
13  const [c, d] = a.length > b.length ? [a, b] : [b, a];
14  return c.filter((value) => d.includes(value));
15}
16
17export function replaceValue<T>(values: T[], original: T, replacement: T): T[] {
18  const index = values.indexOf(original);
19  if (index > -1) {
20    values[index] = replacement;
21  }
22  return values;
23}
24
25/** lodash.uniqBy */
26export function uniqBy<T>(array: T[], key: (item: T) => string): T[] {
27  const seen: { [key: string]: boolean } = {};
28  return array.filter((item) => {
29    const k = key(item);
30    if (seen[k]) {
31      return false;
32    }
33    seen[k] = true;
34    return true;
35  });
36}
37
38/** `lodash.chunk` */
39export function chunk<T>(array: T[], size: number): T[][] {
40  const chunked = [];
41  let index = 0;
42  while (index < array.length) {
43    chunked.push(array.slice(index, (index += size)));
44  }
45  return chunked;
46}
47
48/** `lodash.groupBy` */
49export function groupBy<T, K extends keyof any>(list: T[], getKey: (item: T) => K): Record<K, T[]> {
50  return list.reduce(
51    (previous, currentItem) => {
52      const group = getKey(currentItem);
53      if (!previous[group]) {
54        previous[group] = [];
55      }
56      previous[group].push(currentItem);
57      return previous;
58    },
59    {} as Record<K, T[]>
60  );
61}
62