Skip to content
Navigation Menu
{{ message }}
-
Notifications
You must be signed in to change notification settings - Fork 0
Expand file tree
/
Copy pathBaseArrayHelper.php
More file actions
344 lines (307 loc) · 12.1 KB
/
Copy pathBaseArrayHelper.php
File metadata and controls
344 lines (307 loc) · 12.1 KB
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
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
<?php
declare(strict_types=1);
namespace Infocyph\ArrayKit\Array;
use ArrayAccess;
use InvalidArgumentException;
class BaseArrayHelper
{
/**
* Check if the given value is an array or an instance of ArrayAccess.
*
* @param mixed $value The value to check.
* @return bool True if the value is accessible, false otherwise.
*/
public static function accessible(mixed $value): bool
{
return is_array($value) || $value instanceof ArrayAccess;
}
/**
* Check if all elements in the array pass the given truth test.
*
* This function applies a callback to each element of the array.
* If the callback returns true for all elements, the function returns true.
* Otherwise, it returns false.
*
* @param array<array-key, mixed> $array The array to be evaluated.
* @param callable $callback The callback function to apply to each element.
* @return bool True if all elements pass the truth test, false otherwise.
*/
public static function all(array $array, callable $callback): bool
{
return static::isAll($array, $callback);
}
/**
* Check if at least one element in the array passes a given truth test.
*
* This function is an alias for haveAny, which is a more descriptive name.
* It is provided for syntactic sugar, as it is very common to want to
* check if at least one item in an array matches a given criteria.
*
* @param array<array-key, mixed> $array The array to check.
* @param callable $callback The callback to apply to each element.
* @return bool True if at least one element passes the test, false otherwise.
*/
public static function any(array $array, callable $callback): bool
{
return static::haveAny($array, $callback);
}
/**
* Filter an array by rejecting elements based on a callback function or value.
*
* This function takes an array and a callback or value as parameters.
* If the callback is callable, it applies the callback to each element of the array.
* Elements for which the callback returns false are kept.
* If the callback is a value, elements equal to this value are rejected.
* The function returns an array with the same type of indices as the input array.
*
* @param array<array-key, mixed> $array The array to be filtered.
* @param mixed $callback The callback function or value for filtering.
* @return array<array-key, mixed> The array with elements rejected based on the callback or value.
*/
public static function doReject(array $array, mixed $callback): array
{
if (is_callable($callback)) {
return array_filter(
$array,
fn($val, $key) => !$callback($val, $key),
ARRAY_FILTER_USE_BOTH,
);
}
return array_filter($array, fn($val) => $val != $callback);
}
/**
* Search the array for a given value and return its key if found.
*
* @param array<array-key, mixed> $array The array to search.
* @param callable $callback The callback to use for searching.
*
* @return int|string|null The key of the value if found, or null if not found.
*/
public static function findKey(array $array, callable $callback): int|string|null
{
foreach ($array as $key => $value) {
if ($callback($value, $key) === true) {
return $key;
}
}
return null;
}
/**
* Remove one or multiple array items from an array.
*
* This function takes an array and a key or array of keys as parameters.
* It then iterates over the given keys, and unsets the corresponding
* items from the array.
*
* @param array<array-key, mixed> $array The array from which to remove items.
* @param int|string|array<int, int|string> $keys The key or array of keys to be removed.
*/
public static function forget(array &$array, int|string|array $keys): void
{
foreach ((array) $keys as $key) {
unset($array[$key]);
}
}
/**
* Check if all the given keys exist in the array.
*
* @param array<array-key, mixed> $array The array to search.
* @param int|string|array<int, int|string> $keys The key(s) to check for existence.
*
* @return bool True if all the given keys exist in the array, false otherwise.
*/
public static function has(array $array, int|string|array $keys): bool
{
$keys = (array) $keys;
if (empty($keys)) {
return false;
}
return array_all($keys, fn(int|string $key): bool => array_key_exists($key, $array));
}
/**
* Check if at least one of the given keys exists in the array.
*
* This function accepts a single key or an array of keys and
* determines whether at least one of them exists within the
* provided array. If any key is found, the function returns
* true. Otherwise, it returns false.
*
* @param array<array-key, mixed> $array The array to search.
* @param int|string|array<int, int|string> $keys The key(s) to check for existence.
* @return bool True if at least one key exists in the array, false otherwise.
*/
public static function hasAny(array $array, int|string|array $keys): bool
{
$keys = (array) $keys;
if (empty($keys)) {
return false;
}
return array_any($keys, fn(int|string $key): bool => array_key_exists($key, $array));
}
/**
* Determine if at least one element in the array passes the given truth test.
*
* @param array<array-key, mixed> $array The array to search.
* @param callable $callback The callback to use for searching.
* @return bool Whether at least one element passed the truth test.
*/
public static function haveAny(array $array, callable $callback): bool
{
return array_any($array, fn($value, $key) => $callback($value, $key) === true);
}
/**
* Determine if all elements in the array pass the given truth test.
*
* @param array<array-key, mixed> $array The array to search.
* @param callable $callback The callback to use for searching.
* @return bool Whether all elements passed the truth test.
*/
public static function isAll(array $array, callable $callback): bool
{
return array_all($array, fn($value, $key) => !($callback($value, $key) === false));
}
/**
* Check if an array is multi-dimensional.
*
* This method is a shortcut for checking if an array is multi-dimensional.
* It checks if the array is an array and if the count of the array is not
* equal to the count of the array with the COUNT_RECURSIVE flag.
*
* @param mixed $array The array to check.
* @return bool True if the array is multi-dimensional, false otherwise.
*/
public static function isMultiDimensional(mixed $array): bool
{
return is_array($array)
&& count($array) !== count($array, COUNT_RECURSIVE);
}
/**
* Retrieve one or multiple random items from an array.
*
* By default, this function returns a single item from the array.
* If you pass a number as the second argument, it will return that
* number of items. If you set the third argument to `true`, the
* keys from the original array are preserved in the returned array.
*
* @param array<array-key, mixed> $array The array from which to retrieve random items.
* @param int|null $number The number of items to retrieve. If null, a single item is returned.
* @param bool $preserveKeys Whether to preserve the keys from the original array.
*
* @return mixed The retrieved item(s) from the array.
*
* @throws InvalidArgumentException If the user requested more items than the array contains.
*/
public static function random(array $array, ?int $number = null, bool $preserveKeys = false): mixed
{
$count = count($array);
if ($count === 0 || ($number !== null && $number <= 0)) {
return ($number === null) ? null : [];
}
if ($number === null) {
$randKey = array_rand($array);
return $array[$randKey];
}
if ($number > $count) {
throw new InvalidArgumentException("You requested $number items, but array only has $count.");
}
$keys = (array) array_rand($array, $number);
// intersect is ~30 % faster than manual loop for large n
$picked = array_intersect_key($array, array_flip($keys));
return $preserveKeys ? $picked : array_values($picked);
}
/**
* Generate an array containing a sequence of numbers.
*
* This function creates an array of numbers starting from $start up to $end,
* incrementing by $step. If $step is zero, an empty array is returned.
*
* @param int $start The starting number of the sequence.
* @param int $end The ending number of the sequence.
* @param int $step The increment between each number in the sequence. Defaults to 1.
* @return array<int, int> An array containing the sequence of numbers.
*/
public static function range(int $start, int $end, int $step = 1): array
{
if ($step === 0) {
// We could throw an exception, or return empty:
return [];
}
return range($start, $end, $step);
}
/* ------------------------------------------------------------------------
| Additional "Sugar" Methods (Point 1)
---------------------------------------------------------------------- */
/**
* Pass the array to the given callback and return it.
*
* Useful for tapping into a fluent method chain for debugging.
*
* @param array<array-key, mixed> $array The array to be tapped.
* @param callable $callback The callback to apply to the array.
* @return array<array-key, mixed> The original array.
*/
public static function tap(array $array, callable $callback): array
{
$callback($array);
return $array;
}
/**
* Create an array of the specified length and fill it with the results of the
* given callback function. If the callback is not provided, the array will be
* filled with the numbers 1 through $number.
*
* Example:
* ArrayKit::helper()->times(3, function ($i) {
* return "Row #{$i}";
* });
* // Output: ["Row #1", "Row #2", "Row #3"]
*
* @param int $number The length of the array.
* @param callable|null $callback The callback function to use.
* @return array<int, mixed> The filled array.
*/
public static function times(int $number, ?callable $callback = null): array
{
$results = [];
if ($number < 1) {
return $results;
}
for ($i = 1; $i <= $number; $i++) {
$results[] = $callback ? $callback($i) : $i;
}
return $results;
}
/**
* Unwrap a value from an array if it contains exactly one element.
*
* This method checks if the given value is an array. If it is not,
* the value is returned as is. If the value is an array with exactly
* one element, that element is returned. Otherwise, the array itself
* is returned.
*
* @param mixed $value The value to potentially unwrap.
* @return mixed The unwrapped value or the original array.
*/
public static function unWrap(mixed $value): mixed
{
if (!is_array($value)) {
return $value;
}
return (count($value) === 1) ? reset($value) : $value;
}
/**
* Wrap a value in an array if it's not already an array; otherwise return the array as is.
*
* If the value is empty, an empty array is returned.
*
* @param mixed $value The value to wrap.
* @return array<array-key, mixed> The wrapped value.
*/
public static function wrap(mixed $value): array
{
if (empty($value)) {
return [];
}
return is_array($value) ? $value : [$value];
}
}
You can’t perform that action at this time.
