js-powerkit 1.0.0
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- package/LICENSE +21 -0
- package/README.md +519 -0
- package/package.json +48 -0
- package/src/arrayUtils.js +347 -0
- package/src/index.js +8 -0
- package/src/objectUtils.js +423 -0
- package/src/stringUtils.js +319 -0
- package/tests/arrayUtils.test.js +204 -0
- package/tests/objectUtils.test.js +211 -0
- package/tests/stringUtils.test.js +220 -0
|
@@ -0,0 +1,347 @@
|
|
|
1
|
+
/**
|
|
2
|
+
* Array Utility Functions
|
|
3
|
+
* @module array
|
|
4
|
+
*/
|
|
5
|
+
|
|
6
|
+
/**
|
|
7
|
+
* Splits an array into chunks of a specified size.
|
|
8
|
+
* @param {Array} arr - The input array.
|
|
9
|
+
* @param {number} size - The size of each chunk.
|
|
10
|
+
* @returns {Array} An array of chunks.
|
|
11
|
+
* @example
|
|
12
|
+
* chunk([1, 2, 3, 4, 5], 2); // [[1, 2], [3, 4], [5]]
|
|
13
|
+
*/
|
|
14
|
+
export const chunk = (arr, size) => {
|
|
15
|
+
if (!Array.isArray(arr)) throw new TypeError('Input must be an array');
|
|
16
|
+
if (typeof size !== 'number' || size <= 0) throw new TypeError('Size must be a positive number');
|
|
17
|
+
const chunks = [];
|
|
18
|
+
for (let i = 0; i < arr.length; i += size) {
|
|
19
|
+
chunks.push(arr.slice(i, i + size));
|
|
20
|
+
}
|
|
21
|
+
return chunks;
|
|
22
|
+
}
|
|
23
|
+
|
|
24
|
+
/**
|
|
25
|
+
* Flattens a nested array to a specified depth.
|
|
26
|
+
* @param {Array} arr - The input array.
|
|
27
|
+
* @param {number} [depth=1] - The depth to flatten.
|
|
28
|
+
* @returns {Array} The flattened array.
|
|
29
|
+
* @example
|
|
30
|
+
* flatten([1, [2, [3, 4]], 5]); // [1, 2, [3, 4], 5]
|
|
31
|
+
*/
|
|
32
|
+
export const flatten = (arr, depth = 1) => {
|
|
33
|
+
if (!Array.isArray(arr)) throw new TypeError('Input must be an array');
|
|
34
|
+
return arr.flat(depth);
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
/**
|
|
38
|
+
* Removes duplicate elements from an array.
|
|
39
|
+
* @param {Array} arr - The input array.
|
|
40
|
+
* @returns {Array} The array with duplicates removed.
|
|
41
|
+
* @example
|
|
42
|
+
* unique([1, 2, 2, 3, 4, 4]); // [1, 2, 3, 4]
|
|
43
|
+
*/
|
|
44
|
+
export const unique = (arr) => {
|
|
45
|
+
if (!Array.isArray(arr)) throw new TypeError('Input must be an array');
|
|
46
|
+
return [...new Set(arr)];
|
|
47
|
+
}
|
|
48
|
+
|
|
49
|
+
/**
|
|
50
|
+
* Shuffles the elements of an array in place.
|
|
51
|
+
* @param {Array} arr - The input array.
|
|
52
|
+
* @returns {Array} The shuffled array.
|
|
53
|
+
* @example
|
|
54
|
+
* shuffle([1, 2, 3, 4]); // [3, 1, 4, 2] (random order)
|
|
55
|
+
*/
|
|
56
|
+
export const shuffle = (arr) => {
|
|
57
|
+
if (!Array.isArray(arr)) throw new TypeError('Input must be an array');
|
|
58
|
+
const shuffled = [...arr];
|
|
59
|
+
for (let i = shuffled.length - 1; i > 0; i--) {
|
|
60
|
+
const j = Math.floor(Math.random() * (i + 1));
|
|
61
|
+
[shuffled[i], shuffled[j]] = [shuffled[j], shuffled[i]];
|
|
62
|
+
}
|
|
63
|
+
return shuffled;
|
|
64
|
+
}
|
|
65
|
+
|
|
66
|
+
/**
|
|
67
|
+
* Gets a random element from an array
|
|
68
|
+
* @param {Array} arr - The array
|
|
69
|
+
* @returns {*} Random element
|
|
70
|
+
* @example
|
|
71
|
+
* randomElement([1, 2, 3, 4, 5]); // 5
|
|
72
|
+
*/
|
|
73
|
+
export const randomElement = (arr) => {
|
|
74
|
+
if (!Array.isArray(arr) || arr.length === 0) return undefined;
|
|
75
|
+
return arr[Math.floor(Math.random() * arr.length)];
|
|
76
|
+
};
|
|
77
|
+
|
|
78
|
+
/**
|
|
79
|
+
* Removes falsy values from an array
|
|
80
|
+
* @param {Array} arr - The array to compact
|
|
81
|
+
* @returns {Array} Array without falsy values
|
|
82
|
+
* @example
|
|
83
|
+
* compact([0, 1, false, 2, '', 3, null, undefined, NaN]); // [1, 2, 3]
|
|
84
|
+
*/
|
|
85
|
+
export const compact = (arr) => {
|
|
86
|
+
if (!Array.isArray(arr)) return [];
|
|
87
|
+
return arr.filter(Boolean);
|
|
88
|
+
};
|
|
89
|
+
|
|
90
|
+
/**
|
|
91
|
+
* Sorts an array of objects by a property.
|
|
92
|
+
* @param {Array} arr - The input array.
|
|
93
|
+
* @param {string} prop - The property to sort by.
|
|
94
|
+
* @param {string} [order='asc'] - The sort order ('asc' or 'desc').
|
|
95
|
+
* @returns {Array} The sorted array.
|
|
96
|
+
* @example
|
|
97
|
+
* sortBy([{a: 2}, {a: 1}], 'a'); // [{a: 1}, {a: 2}]
|
|
98
|
+
*/
|
|
99
|
+
export const sortBy = (arr, prop, order = 'asc') => {
|
|
100
|
+
if (!Array.isArray(arr)) throw new TypeError('Input must be an array');
|
|
101
|
+
return [...arr].sort((a, b) => {
|
|
102
|
+
if (a[prop] < b[prop]) return order === 'asc' ? -1 : 1;
|
|
103
|
+
if (a[prop] > b[prop]) return order === 'asc' ? 1 : -1;
|
|
104
|
+
return 0;
|
|
105
|
+
});
|
|
106
|
+
}
|
|
107
|
+
|
|
108
|
+
/**
|
|
109
|
+
* Groups an array of objects by a property.
|
|
110
|
+
* @param {Array} arr - The input array.
|
|
111
|
+
* @param {string} prop - The property to group by.
|
|
112
|
+
* @returns {Object} An object with grouped arrays.
|
|
113
|
+
* @example
|
|
114
|
+
* groupBy([{type: 'a', val: 1}, {type: 'b', val: 2}, {type: 'a', val: 3}], 'type');
|
|
115
|
+
* // {a: [{type: 'a', val: 1}, {type: 'a', val: 3}], b: [{type: 'b', val: 2}]}
|
|
116
|
+
*/
|
|
117
|
+
export const groupBy = (arr, prop) => {
|
|
118
|
+
if (!Array.isArray(arr)) throw new TypeError('Input must be an array');
|
|
119
|
+
return arr.reduce((groups, item) => {
|
|
120
|
+
const key = item[prop];
|
|
121
|
+
if (!groups[key]) groups[key] = [];
|
|
122
|
+
groups[key].push(item);
|
|
123
|
+
return groups;
|
|
124
|
+
}, {});
|
|
125
|
+
}
|
|
126
|
+
|
|
127
|
+
/**
|
|
128
|
+
* Finds the intersection of two arrays.
|
|
129
|
+
* @param {Array} arr1 - The first array.
|
|
130
|
+
* @param {Array} arr2 - The second array.
|
|
131
|
+
* @returns {Array} The intersection array.
|
|
132
|
+
* @example
|
|
133
|
+
* intersection([1, 2, 3], [2, 3, 4]); // [2, 3]
|
|
134
|
+
*/
|
|
135
|
+
export const intersection = (arr1, arr2) => {
|
|
136
|
+
if (!Array.isArray(arr1) || !Array.isArray(arr2)) throw new TypeError('Inputs must be arrays');
|
|
137
|
+
return arr1.filter(item => arr2.includes(item));
|
|
138
|
+
}
|
|
139
|
+
|
|
140
|
+
/**
|
|
141
|
+
* Finds the difference of two arrays.
|
|
142
|
+
* @param {Array} arr1 - The first array.
|
|
143
|
+
* @param {Array} arr2 - The second array.
|
|
144
|
+
* @returns {Array} The difference array.
|
|
145
|
+
* @example
|
|
146
|
+
* difference([1, 2, 3], [2, 3, 4]); // [1]
|
|
147
|
+
*/
|
|
148
|
+
export const difference = (arr1, arr2) => {
|
|
149
|
+
if (!Array.isArray(arr1) || !Array.isArray(arr2)) throw new TypeError('Inputs must be arrays');
|
|
150
|
+
return arr1.filter(item => !arr2.includes(item));
|
|
151
|
+
}
|
|
152
|
+
|
|
153
|
+
/**
|
|
154
|
+
* Finds the union of two arrays.
|
|
155
|
+
* @param {Array} arr1 - The first array.
|
|
156
|
+
* @param {Array} arr2 - The second array.
|
|
157
|
+
* @returns {Array} The union array.
|
|
158
|
+
* @example
|
|
159
|
+
* union([1, 2, 3], [2, 3, 4]); // [1, 2, 3, 4]
|
|
160
|
+
*/
|
|
161
|
+
export const union = (arr1, arr2) => {
|
|
162
|
+
if (!Array.isArray(arr1) || !Array.isArray(arr2)) throw new TypeError('Inputs must be arrays');
|
|
163
|
+
return [...new Set([...arr1, ...arr2])];
|
|
164
|
+
}
|
|
165
|
+
|
|
166
|
+
/**
|
|
167
|
+
* Zips multiple arrays together.
|
|
168
|
+
* @param {...Array} arrays - The arrays to zip.
|
|
169
|
+
* @returns {Array} The zipped array.
|
|
170
|
+
* @example
|
|
171
|
+
* zip([1, 2], ['a', 'b'], [true, false]); // [[1, 'a', true], [2, 'b', false]]
|
|
172
|
+
*/
|
|
173
|
+
export const zip = (...arrays) => {
|
|
174
|
+
arrays.forEach(arr => {
|
|
175
|
+
if (!Array.isArray(arr)) throw new TypeError('All inputs must be arrays');
|
|
176
|
+
});
|
|
177
|
+
const minLength = Math.min(...arrays.map(arr => arr.length));
|
|
178
|
+
const result = [];
|
|
179
|
+
for (let i = 0; i < minLength; i++) {
|
|
180
|
+
result.push(arrays.map(arr => arr[i]));
|
|
181
|
+
}
|
|
182
|
+
return result;
|
|
183
|
+
}
|
|
184
|
+
|
|
185
|
+
/**
|
|
186
|
+
* Creates an array of numbers from start to end.
|
|
187
|
+
* @param {number} start - The start number.
|
|
188
|
+
* @param {number} end - The end number.
|
|
189
|
+
* @param {number} [step=1] - The step size.
|
|
190
|
+
* @returns {Array} The range array.
|
|
191
|
+
* @example
|
|
192
|
+
* range(1, 5); // [1, 2, 3, 4, 5]
|
|
193
|
+
*/
|
|
194
|
+
export const range = (start, end, step = 1) => {
|
|
195
|
+
if (typeof start !== 'number' || typeof end !== 'number') throw new TypeError('Start and end must be numbers');
|
|
196
|
+
const result = [];
|
|
197
|
+
for (let i = start; i <= end; i += step) {
|
|
198
|
+
result.push(i);
|
|
199
|
+
}
|
|
200
|
+
return result;
|
|
201
|
+
}
|
|
202
|
+
|
|
203
|
+
/**
|
|
204
|
+
* Finds the maximum value in an array
|
|
205
|
+
* @param {Array} arr - The array
|
|
206
|
+
* @returns {*} Maximum value
|
|
207
|
+
* @example
|
|
208
|
+
* max([1, 5, 3, 9, 2]); // 9
|
|
209
|
+
*/
|
|
210
|
+
export const max = (arr) => {
|
|
211
|
+
if (!Array.isArray(arr) || arr.length === 0) return undefined;
|
|
212
|
+
return Math.max(...arr);
|
|
213
|
+
};
|
|
214
|
+
|
|
215
|
+
/**
|
|
216
|
+
* Finds the minimum value in an array
|
|
217
|
+
* @param {Array} arr - The array
|
|
218
|
+
* @returns {*} Minimum value
|
|
219
|
+
* @example
|
|
220
|
+
* min([1, 5, 3, 9, 2]); // 1
|
|
221
|
+
*/
|
|
222
|
+
export const min = (arr) => {
|
|
223
|
+
if (!Array.isArray(arr) || arr.length === 0) return undefined;
|
|
224
|
+
return Math.min(...arr);
|
|
225
|
+
};
|
|
226
|
+
|
|
227
|
+
/**
|
|
228
|
+
* Calculates the sum of array elements
|
|
229
|
+
* @param {Array} arr - The array of numbers
|
|
230
|
+
* @returns {number} Sum of elements
|
|
231
|
+
* @example
|
|
232
|
+
* sum([1, 2, 3, 4, 5]); // 15
|
|
233
|
+
*/
|
|
234
|
+
export const sum = (arr) => {
|
|
235
|
+
if (!Array.isArray(arr)) return 0;
|
|
236
|
+
return arr.reduce((total, num) => total + (Number(num) || 0), 0);
|
|
237
|
+
};
|
|
238
|
+
|
|
239
|
+
/**
|
|
240
|
+
* Calculates the average of array elements
|
|
241
|
+
* @param {Array} arr - The array of numbers
|
|
242
|
+
* @returns {number} Average value
|
|
243
|
+
* @example
|
|
244
|
+
* average([1, 2, 3, 4, 5]); // 3
|
|
245
|
+
*/
|
|
246
|
+
export const average = (arr) => {
|
|
247
|
+
if (!Array.isArray(arr) || arr.length === 0) return 0;
|
|
248
|
+
return sum(arr) / arr.length;
|
|
249
|
+
};
|
|
250
|
+
|
|
251
|
+
/**
|
|
252
|
+
* Counts occurrences of each element
|
|
253
|
+
* @param {Array} arr - The array
|
|
254
|
+
* @returns {Object} Object with counts
|
|
255
|
+
* @example
|
|
256
|
+
* countOccurrences([1, 2, 2, 3, 3, 3]); // { '1': 1, '2': 2, '3': 3 }
|
|
257
|
+
*/
|
|
258
|
+
export const countOccurrences = (arr) => {
|
|
259
|
+
if (!Array.isArray(arr)) return {};
|
|
260
|
+
return arr.reduce((count, item) => {
|
|
261
|
+
count[item] = (count[item] || 0) + 1;
|
|
262
|
+
return count;
|
|
263
|
+
}, {});
|
|
264
|
+
};
|
|
265
|
+
|
|
266
|
+
/**
|
|
267
|
+
* Removes elements from array by value
|
|
268
|
+
* @param {Array} arr - The array
|
|
269
|
+
* @param {*} value - Value to remove
|
|
270
|
+
* @returns {Array} Array without the value
|
|
271
|
+
* @example
|
|
272
|
+
* remove([1, 2, 3, 2, 4], 2); // [1, 3, 4]
|
|
273
|
+
*/
|
|
274
|
+
export const remove = (arr, value) => {
|
|
275
|
+
if (!Array.isArray(arr)) return [];
|
|
276
|
+
return arr.filter(item => item !== value);
|
|
277
|
+
};
|
|
278
|
+
|
|
279
|
+
/**
|
|
280
|
+
* Takes first n elements from array
|
|
281
|
+
* @param {Array} arr - The array
|
|
282
|
+
* @param {number} n - Number of elements
|
|
283
|
+
* @returns {Array} First n elements
|
|
284
|
+
* @example
|
|
285
|
+
* take([10, 21, 31, 41, 51], 4); // [10, 21, 31, 41]
|
|
286
|
+
*/
|
|
287
|
+
export const take = (arr, n = 1) => {
|
|
288
|
+
if (!Array.isArray(arr)) return [];
|
|
289
|
+
return arr.slice(0, n);
|
|
290
|
+
};
|
|
291
|
+
|
|
292
|
+
/**
|
|
293
|
+
* Drops first n elements from array
|
|
294
|
+
* @param {Array} arr - The array
|
|
295
|
+
* @param {number} n - Number of elements to drop
|
|
296
|
+
* @returns {Array} Array without first n elements
|
|
297
|
+
* @example
|
|
298
|
+
* drop([1, 2, 3, 4, 5], 2); // [3, 4, 5]
|
|
299
|
+
*/
|
|
300
|
+
export const drop = (arr, n = 1) => {
|
|
301
|
+
if (!Array.isArray(arr)) return [];
|
|
302
|
+
return arr.slice(n);
|
|
303
|
+
};
|
|
304
|
+
|
|
305
|
+
/**
|
|
306
|
+
* Checks if array includes all values
|
|
307
|
+
* @param {Array} arr - The array
|
|
308
|
+
* @param {Array} values - Values to check
|
|
309
|
+
* @returns {boolean} True if all values are included
|
|
310
|
+
* @example
|
|
311
|
+
* includesAll([1, 2, 3, 4], [2, 3]); // true
|
|
312
|
+
* includesAll([1, 2, 3], [2, 5]); // false
|
|
313
|
+
*/
|
|
314
|
+
export const includesAll = (arr, values) => {
|
|
315
|
+
if (!Array.isArray(arr) || !Array.isArray(values)) return false;
|
|
316
|
+
return values.every(val => arr.includes(val));
|
|
317
|
+
};
|
|
318
|
+
|
|
319
|
+
/**
|
|
320
|
+
* Checks if array includes any of the values
|
|
321
|
+
* @param {Array} arr - The array
|
|
322
|
+
* @param {Array} values - Values to check
|
|
323
|
+
* @returns {boolean} True if any value is included
|
|
324
|
+
* @example
|
|
325
|
+
* includesAny([1, 2, 3], [3, 4, 5]); // true
|
|
326
|
+
* includesAny([1, 2, 3], [4, 5, 6]); // false
|
|
327
|
+
*/
|
|
328
|
+
export const includesAny = (arr, values) => {
|
|
329
|
+
if (!Array.isArray(arr) || !Array.isArray(values)) return false;
|
|
330
|
+
return values.some(val => arr.includes(val));
|
|
331
|
+
};
|
|
332
|
+
|
|
333
|
+
/**
|
|
334
|
+
* Rotates array elements
|
|
335
|
+
* @param {Array} arr - The array
|
|
336
|
+
* @param {number} positions - Number of positions to rotate
|
|
337
|
+
* @returns {Array} Rotated array
|
|
338
|
+
* @example
|
|
339
|
+
* rotate([1, 2, 3, 4, 5], 2); // [3, 4, 5, 1, 2]
|
|
340
|
+
* rotate([1, 2, 3, 4, 5], -2); // [4, 5, 1, 2, 3]
|
|
341
|
+
*/
|
|
342
|
+
export const rotate = (arr, positions = 1) => {
|
|
343
|
+
if (!Array.isArray(arr) || arr.length === 0) return [];
|
|
344
|
+
const len = arr.length;
|
|
345
|
+
const shift = ((positions % len) + len) % len;
|
|
346
|
+
return [...arr.slice(shift), ...arr.slice(0, shift)];
|
|
347
|
+
};
|