-
Notifications
You must be signed in to change notification settings - Fork 0
/
array-utils.ts
128 lines (118 loc) · 4.06 KB
/
array-utils.ts
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
/**
* Recursively flattens an array by a specific propertyName or property accessor.
* It does not mutate the items, meaning the items keeps their original child array.
* @param array Array to flatten
* @param key Selector for the child property
* @returns An flatten array
*/
export function flattenTree<T = object>(array: T[] = [], key: string | ((s: T) => string)): T[] {
const flat: T[] = [];
array.forEach((child) => {
flat.push(child);
const childArray: T[] = (key instanceof Function ? key(child) : (child as any)[key]) || [];
flat.push(...flattenTree<T>(childArray, key));
});
return flat;
}
/**
* @returns A random entry from an array
*
* Based on Math.random()
* @param array The array of which you want a random entry
*/
export function getRandomEntry<T>(array: T[], arrayToPopulate?: T[], tryCount?: number): T {
const randomIndex = Math.floor(Math.random() * array.length);
const randomEntry = array[randomIndex];
/**
* If arrayToPopulate is provided; run this method again.
* Repeat until the maxium amount of tries has been done
* so we avoid getting stuck in an infinite loop
* (which could happen if @param array only has a single entry)
*/
tryCount = tryCount || 5;
if (tryCount > 0 && arrayToPopulate && arrayToPopulate.includes(randomEntry)) {
tryCount--;
return getRandomEntry(array, arrayToPopulate);
}
return randomEntry;
}
/**
* Groups an array of items into multiple arrays,
* grouped by a common property
* @param array All properties
*/
export function groupArrayByProperty<T = any>(
array: T[],
key: string | ((s: T) => string | number)
): T[][] {
const grouped: T[][] = [];
// Get an array with the relation names and remove dublicates
let uniqueValues: string[] = array.map((item) => {
let value = (key instanceof Function ? key(item) : (item as any)[key]);
if (typeof value === 'string') {
value = value.toLocaleLowerCase();
}
return value;
}).filter((val) => (!!val && val.length > 0) || typeof val === 'number');
uniqueValues = removeDuplicates(uniqueValues);
// For each property, push in it's related items
uniqueValues.forEach((propertyValue) => {
grouped.push(array.filter((item) =>
(key instanceof Function ? key(item) : (item as any)[key]) === propertyValue));
});
return grouped;
}
/**
* Groups an array of objects by a key
* example: groupOptionsBy([
* {a: 1, b: 'group1'},
* {a: 1, b: 'group2'},
* {a: 1, b: 'group2'}
* ],
* 'b'
* )
* returns:
* [
* label: 'group1',
* options: [
* {a: 1, b: 'group1'}
* ],
* 'group2',
* options: [
* {a: 1, b: 'group2'},
* {a: 1, b: 'group2'}
* ]
* ]
* Note: if the key is not defined for an object, the object will not be a part of the result!
* @param {any[]} array
* @param {(string | ((string) => string))} key: either a field or
* a function returning a value to group by
* @returns {IOptionGroup[]}
* @memberof AbstractFormInput
*/
// export function groupOptionsBy<T = ISelectOption>(
// array: T[], key: string | ((s) => string)): IOptionGroup[] {
// return array.reduce((accumulatedGroups, item) => {
// // Get the GroupName on the item
// const label = (key instanceof Function ? key(item) : item[key]) || '';
// // Find the group from the previous added group
// const group = accumulatedGroups.find(r => r && (r.label || '') === label);
// if (group) {
// group.options.push(item);
// } else {
// // If no group was found, add it
// accumulatedGroups.push({ label: label, options: [item] });
// }
// return accumulatedGroups;
// }, []);
// }
/**
* Creates and returns a new array, clearing
* duplicates with new Set().
* @param val The array to remove duplicates from
*
* @returns An edited copy of @param val
*/
export function removeDuplicates<T = any>(val: T[]): T[] {
return Array.from(new Set(val));
}