Completed
Push — master ( 9525b9...ded22b )
by Xu
06:38
created

ArrayHelper::random()   B

Complexity

Conditions 6
Paths 10

Size

Total Lines 21
Code Lines 14

Duplication

Lines 0
Ratio 0 %

Importance

Changes 0
Metric Value
cc 6
eloc 14
nc 10
nop 2
dl 0
loc 21
rs 8.7624
c 0
b 0
f 0
1
<?php
2
/**
3
 * @link http://www.tintsoft.com/
4
 * @copyright Copyright (c) 2012 TintSoft Technology Co. Ltd.
5
 * @license http://www.tintsoft.com/license/
6
 */
7
8
namespace yuncms\helpers;
9
10
use ArrayAccess;
11
use InvalidArgumentException;
12
use yuncms\base\Collection;
13
14
/**
15
 * Class ArrayHelper
16
 * @package yuncms\helpers
17
 * @author Tongle Xu <[email protected]>
18
 */
19
class ArrayHelper extends \yii\helpers\ArrayHelper
20
{
21
    /**
22
     * 判断给定的值是否是可访问的数组
23
     *
24
     * @param  mixed $value
25
     * @return bool
26
     */
27
    public static function accessible($value): bool
28
    {
29
        return is_array($value) || $value instanceof ArrayAccess;
30
    }
31
32
    /**
33
     * 如果元素不存在,使用 "." 符号添加元素到数组中。
34
     *
35
     * @param  array $array
36
     * @param  string $key
37
     * @param  mixed $value
38
     * @return array
39
     */
40
    public static function add($array, $key, $value)
41
    {
42
        if (is_null(static::get($array, $key))) {
43
            static::set($array, $key, $value);
44
        }
45
        return $array;
46
    }
47
48
    /**
49
     * 将一组数组合并到一个数组中。
50
     *
51
     * @param  array $array
52
     * @return array
53
     */
54
    public static function collapse($array)
55
    {
56
        $results = [];
57
        foreach ($array as $values) {
58
            if ($values instanceof Collection) {
59
                $values = $values->all();
60
            } elseif (!is_array($values)) {
61
                continue;
62
            }
63
            $results = array_merge($results, $values);
64
        }
65
        return $results;
66
    }
67
68
    /**
69
     * 交叉连接给定的数组,返回所有可能的排列。
70
     *
71
     * @param  array ...$arrays
72
     * @return array
73
     */
74
    public static function crossJoin(...$arrays)
75
    {
76
        $results = [[]];
77
        foreach ($arrays as $index => $array) {
78
            $append = [];
79
            foreach ($results as $product) {
80
                foreach ($array as $item) {
81
                    $product[$index] = $item;
82
                    $append[] = $product;
83
                }
84
            }
85
            $results = $append;
86
        }
87
        return $results;
88
    }
89
90
    /**
91
     * 将数组分成两个数组。 一个用键和另一个用值。
92
     *
93
     * @param  array $array
94
     * @return array
95
     */
96
    public static function divide($array)
97
    {
98
        return [array_keys($array), array_values($array)];
99
    }
100
101
    /**
102
     * 用点来展平多维关联数组。
103
     *
104
     * @param  array $array
105
     * @param  string $prepend
106
     * @return array
107
     */
108
    public static function dot($array, $prepend = '')
109
    {
110
        $results = [];
111
        foreach ($array as $key => $value) {
112
            if (is_array($value) && !empty($value)) {
113
                $results = array_merge($results, static::dot($value, $prepend . $key . '.'));
114
            } else {
115
                $results[$prepend . $key] = $value;
116
            }
117
        }
118
        return $results;
119
    }
120
121
    /**
122
     * 获取给定的数组,除了指定的键数组。
123
     *
124
     * @param  array $array
125
     * @param  array|string $keys
126
     * @return array
127
     */
128
    public static function except($array, $keys)
129
    {
130
        static::forget($array, $keys);
131
        return $array;
132
    }
133
134
    /**
135
     * 确定给定的键是否存在于提供的数组中。
136
     *
137
     * @param  \ArrayAccess|array $array
138
     * @param  string|int $key
139
     * @return bool
140
     */
141
    public static function exists($array, $key)
142
    {
143
        if ($array instanceof ArrayAccess) {
144
            return $array->offsetExists($key);
145
        }
146
        return array_key_exists($key, $array);
147
    }
148
149
    /**
150
     * 返回数组中第一个传递给定真值测试的元素。
151
     *
152
     * @param  array $array
153
     * @param  callable|null $callback
154
     * @param  mixed $default
155
     * @return mixed
156
     */
157
    public static function first($array, callable $callback = null, $default = null)
158
    {
159
        if (is_null($callback)) {
160
            if (empty($array)) {
161
                return $default;
162
            }
163
            foreach ($array as $item) {
164
                return $item;
165
            }
166
        }
167
        foreach ($array as $key => $value) {
168
            if (call_user_func($callback, $value, $key)) {
169
                return $value;
170
            }
171
        }
172
        return $default;
173
    }
174
175
    /**
176
     * 返回数组中传递给定真值测试的最后一个元素。
177
     *
178
     * @param  array $array
179
     * @param  callable|null $callback
180
     * @param  mixed $default
181
     * @return mixed
182
     */
183
    public static function last($array, callable $callback = null, $default = null)
184
    {
185
        if (is_null($callback)) {
186
            return empty($array) ? $default : end($array);
187
        }
188
        return static::first(array_reverse($array, true), $callback, $default);
189
    }
190
191
    /**
192
     * 将多维数组展平成一个级别。
193
     *
194
     * @param  array $array
195
     * @param  int $depth
196
     * @return array
197
     */
198
    public static function flatten($array, $depth = INF)
199
    {
200
        $result = [];
201
        foreach ($array as $item) {
202
            $item = $item instanceof Collection ? $item->all() : $item;
203
            if (!is_array($item)) {
204
                $result[] = $item;
205
            } elseif ($depth === 1) {
206
                $result = array_merge($result, array_values($item));
207
            } else {
208
                $result = array_merge($result, static::flatten($item, $depth - 1));
209
            }
210
        }
211
        return $result;
212
    }
213
214
    /**
215
     * 使用 "." 符号从给定数组中删除一个或多个数组项。
216
     *
217
     * @param  array $array
218
     * @param  array|string $keys
219
     * @return void
220
     */
221
    public static function forget(&$array, $keys)
222
    {
223
        $original = &$array;
224
        $keys = (array)$keys;
225
        if (count($keys) === 0) {
226
            return;
227
        }
228
        foreach ($keys as $key) {
229
            // if the exact key exists in the top-level, remove it
230
            if (static::exists($array, $key)) {
231
                unset($array[$key]);
232
                continue;
233
            }
234
            $parts = explode('.', $key);
235
            // clean up before each pass
236
            $array = &$original;
237
            while (count($parts) > 1) {
238
                $part = array_shift($parts);
239
                if (isset($array[$part]) && is_array($array[$part])) {
240
                    $array = &$array[$part];
241
                } else {
242
                    continue 2;
243
                }
244
            }
245
            unset($array[array_shift($parts)]);
246
        }
247
    }
248
249
    /**
250
     * 使用 "." 符号从数组中获取项目。
251
     *
252
     * @param  \ArrayAccess|array $array
253
     * @param  string $key
254
     * @param  mixed $default
255
     * @return mixed
256
     */
257
    public static function get($array, $key, $default = null)
258
    {
259
        if (!static::accessible($array)) {
260
            return $default;
261
        }
262
        if (is_null($key)) {
0 ignored issues
show
introduced by
The condition is_null($key) can never be true.
Loading history...
263
            return $array;
264
        }
265
        if (static::exists($array, $key)) {
266
            return $array[$key];
267
        }
268
        if (strpos($key, '.') === false) {
269
            return $array[$key] ?? $default;
270
        }
271
        foreach (explode('.', $key) as $segment) {
272
            if (static::accessible($array) && static::exists($array, $segment)) {
273
                $array = $array[$segment];
274
            } else {
275
                return $default;
276
            }
277
        }
278
        return $array;
279
    }
280
281
    /**
282
     * 使用 "." 符号检查数组中是否存在一个或多个项目。
283
     *
284
     * @param  \ArrayAccess|array $array
285
     * @param  string|array $keys
286
     * @return bool
287
     */
288
    public static function has($array, $keys)
289
    {
290
        if (is_null($keys)) {
0 ignored issues
show
introduced by
The condition is_null($keys) can never be true.
Loading history...
291
            return false;
292
        }
293
        $keys = (array)$keys;
294
        if (!$array) {
295
            return false;
296
        }
297
        if ($keys === []) {
298
            return false;
299
        }
300
        foreach ($keys as $key) {
301
            $subKeyArray = $array;
302
            if (static::exists($array, $key)) {
303
                continue;
304
            }
305
            foreach (explode('.', $key) as $segment) {
306
                if (static::accessible($subKeyArray) && static::exists($subKeyArray, $segment)) {
307
                    $subKeyArray = $subKeyArray[$segment];
308
                } else {
309
                    return false;
310
                }
311
            }
312
        }
313
        return true;
314
    }
315
316
    /**
317
     * 确定数组是否是Assoc。
318
     *
319
     * 如果数组没有从零开始的连续数字键,则该数组是“Assoc”。
320
     *
321
     * @param  array $array
322
     * @return bool
323
     */
324
    public static function isAssoc(array $array): bool
325
    {
326
        $keys = array_keys($array);
327
        return array_keys($keys) !== $keys;
328
    }
329
330
    /**
331
     * 获取给定数组中项目的子集。
332
     *
333
     * @param  array $array
334
     * @param  array|string $keys
335
     * @return array
336
     */
337
    public static function only($array, $keys): array
338
    {
339
        return array_intersect_key($array, array_flip((array)$keys));
340
    }
341
342
    /**
343
     * 将一个项目推到数组的开头。
344
     *
345
     * @param  array $array
346
     * @param  mixed $value
347
     * @param  mixed $key
348
     * @return array
349
     */
350
    public static function prepend($array, $value, $key = null): array
351
    {
352
        if (is_null($key)) {
353
            array_unshift($array, $value);
354
        } else {
355
            $array = [$key => $value] + $array;
356
        }
357
        return $array;
358
    }
359
360
    /**
361
     * 从数组中获取一个值,并将其删除。
362
     *
363
     * @param  array $array
364
     * @param  string $key
365
     * @param  mixed $default
366
     * @return mixed
367
     */
368
    public static function pull(&$array, $key, $default = null)
369
    {
370
        $value = static::get($array, $key, $default);
371
        static::forget($array, $key);
372
        return $value;
373
    }
374
375
    /**
376
     * 从数组中获取一个或指定数量的随机值。
377
     *
378
     * @param  array $array
379
     * @param  int|null $number
380
     * @return mixed
381
     *
382
     * @throws \InvalidArgumentException
383
     */
384
    public static function random($array, $number = null)
385
    {
386
        $requested = is_null($number) ? 1 : $number;
387
        $count = count($array);
388
        if ($requested > $count) {
389
            throw new InvalidArgumentException(
390
                "You requested {$requested} items, but there are only {$count} items available."
391
            );
392
        }
393
        if (is_null($number)) {
394
            return $array[array_rand($array)];
395
        }
396
        if ((int)$number === 0) {
397
            return [];
398
        }
399
        $keys = array_rand($array, $number);
400
        $results = [];
401
        foreach ((array)$keys as $key) {
402
            $results[] = $array[$key];
403
        }
404
        return $results;
405
    }
406
407
    /**
408
     * 使用 "." 符号将数组项设置为给定值。
409
     *
410
     * 如果没有键给该方法,整个数组将被替换。
411
     *
412
     * @param  array $array
413
     * @param  string $key
414
     * @param  mixed $value
415
     * @return array
416
     */
417
    public static function set(&$array, $key, $value): array
418
    {
419
        if (is_null($key)) {
0 ignored issues
show
introduced by
The condition is_null($key) can never be true.
Loading history...
420
            return $array = $value;
421
        }
422
        $keys = explode('.', $key);
423
        while (count($keys) > 1) {
424
            $key = array_shift($keys);
425
            // If the key doesn't exist at this depth, we will just create an empty array
426
            // to hold the next value, allowing us to create the arrays to hold final
427
            // values at the correct depth. Then we'll keep digging into the array.
428
            if (!isset($array[$key]) || !is_array($array[$key])) {
429
                $array[$key] = [];
430
            }
431
            $array = &$array[$key];
432
        }
433
        $array[array_shift($keys)] = $value;
434
        return $array;
435
    }
436
437
    /**
438
     * 数组中的元素按随机顺序重新排序
439
     *
440
     * @param  array $array
441
     * @return array
442
     */
443
    public static function shuffle($array)
444
    {
445
        shuffle($array);
446
        return $array;
447
    }
448
449
    /**
450
     * 使用给定的回调过滤数组。
451
     *
452
     * @param  array $array
453
     * @param  callable $callback
454
     * @return array
455
     */
456
    public static function where($array, callable $callback): array
457
    {
458
        return array_filter($array, $callback, ARRAY_FILTER_USE_BOTH);
459
    }
460
461
    /**
462
     * 如果给定的值不是数组,则将其包装为数组。
463
     *
464
     * @param  mixed $value
465
     * @return array
466
     */
467
    public static function wrap($value): array
468
    {
469
        return !is_array($value) ? [$value] : $value;
470
    }
471
472
    /**
473
     * Filters an array to only the values where a given key (the name of a
474
     * sub-array key or sub-object property) is set to a given value.
475
     *
476
     * Array keys are preserved.
477
     *
478
     * @param array|\Traversable $array the array that needs to be indexed or grouped
479
     * @param string|\Closure $key the column name or anonymous function which result will be used to index the array
480
     * @param mixed $value the value that $key should be compared with
481
     * @param bool $strict 是否严格比较
482
     * @return array the filtered array
483
     */
484
    public static function filterByValue($array, $key, $value, bool $strict = false): array
485
    {
486
        $result = [];
487
488
        foreach ($array as $i => $element) {
489
            $elementValue = static::getValue($element, $key);
490
            /** @noinspection TypeUnsafeComparisonInspection */
491
            if (($strict && $elementValue === $value) || (!$strict && $elementValue == $value)) {
492
                $result[$i] = $element;
493
            }
494
        }
495
496
        return $result;
497
    }
498
499
    /**
500
     * 从数组中过滤空字符串。
501
     *
502
     * @param array $arr
503
     * @return array
504
     */
505
    public static function filterEmptyStringsFromArray(array $arr): array
506
    {
507
        return array_filter($arr, function ($value): bool {
508
            return $value !== '';
509
        });
510
    }
511
512
    /**
513
     * 返回给定数组中的第一个键。
514
     *
515
     * @param array $arr
516
     * @return string|int|null The first key, whether that is a number (if the array is numerically indexed) or a string, or null if $arr isn’t an array, or is empty.
517
     */
518
    public static function firstKey(array $arr)
519
    {
520
        /** @noinspection LoopWhichDoesNotLoopInspection */
521
        foreach ($arr as $key => $value) {
522
            return $key;
523
        }
524
525
        return null;
526
    }
527
528
    /**
529
     * 返回给定数组中的第一个值。
530
     *
531
     * @param array $arr
532
     * @return mixed The first value, or null if $arr isn’t an array, or is empty.
533
     */
534
    public static function firstValue(array $arr)
535
    {
536
        return !empty($arr) ? reset($arr) : null;
537
    }
538
539
    /**
540
     * 重命名数组中的项目。如果新Key已经存在于数组中,并且旧Key不存在,数组将保持不变。
541
     *
542
     * @param array $array the array to extract value from
543
     * @param string $oldKey old key name of the array element
544
     * @param string $newKey new key name of the array element
545
     * @param mixed $default the default value to be set if the specified old key does not exist
546
     * @return void
547
     */
548
    public static function rename(array &$array, string $oldKey, string $newKey, $default = null)
549
    {
550
        if (!array_key_exists($newKey, $array) || array_key_exists($oldKey, $array)) {
551
            $array[$newKey] = static::remove($array, $oldKey, $default);
552
        }
553
    }
554
}