GitHub Access Token became invalid

It seems like the GitHub access token used for retrieving details about this repository from GitHub became invalid. This might prevent certain types of inspections from being run (in particular, everything related to pull requests).
Please ask an admin of your repository to re-new the access token on this website.
Completed
Pull Request — master (#18)
by t
04:52 queued 01:14
created

Arrays::columns()   B

Complexity

Conditions 9
Paths 5

Size

Total Lines 28
Code Lines 17

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 16
CRAP Score 9

Importance

Changes 2
Bugs 0 Features 0
Metric Value
cc 9
eloc 17
c 2
b 0
f 0
nc 5
nop 3
dl 0
loc 28
ccs 16
cts 16
cp 1
crap 9
rs 8.0555
1
<?php
2
/**
3
 * Class Arrays
4
 *
5
 * @link https://www.icy2003.com/
6
 * @author icy2003 <[email protected]>
7
 * @copyright Copyright (c) 2017, icy2003
8
 */
9
10
namespace icy2003\php\ihelpers;
11
12
use icy2003\php\C;
13
use icy2003\php\I;
14
15
/**
16
 * 数组类
17
 *
18
 * 常见数组格式的拼装和处理
19
 *
20
 * @test icy2003\php_tests\ihelpers\ArraysTest
21
 */
22
class Arrays
23
{
24
25
    /**
26
     * 以各个元素的某字段值作为键重新指回该元素,此值对于该元素需唯一
27
     *
28
     * @param array  $array 元素可以为数组或者对象
29
     * @param string $index 用来作为键的某字段,不能为 null
30
     * @param boolean $isMerge 是否合并相同键的项到数组,默认否(也就是后者覆盖前者)
31
     *
32
     * @return array
33
     *
34
     * @tested
35
     */
36 1
    public static function indexBy($array, $index, $isMerge = false)
37
    {
38 1
        $result = [];
39 1
        foreach ($array as $row) {
40 1
            $indexValue = I::get($row, $index);
41 1
            if (null === $indexValue) {
42 1
                return [];
43
            }
44 1
            if (false === $isMerge) {
45 1
                $result[$indexValue] = $row;
46
            } else {
47 1
                $result[$indexValue][] = $row;
48
            }
49
        }
50
51 1
        return $result;
52
    }
53
54
    /**
55
     * 选取数组中指定键的某几列
56
     *
57
     * - 简单理解就是:从数据库里查出来几条数据,只拿其中的几个属性
58
     * - 当 $dimension 为 2 时,理解为从几条数据里拿属性
59
     * - 当 $dimension 为 1 时,理解为从一条数据里拿属性
60
     *
61
     * @param array $array
62
     * @param array $keys 某几项字段,支持 I::get 的键格式,如果给 null,则返回原数组
63
     * @param integer $dimension 维度,只能为 1 或 2,默认 2,表示处理二维数组
64
     *
65
     * @return array
66
     *
67
     * @tested
68
     */
69 1
    public static function columns($array, $keys = null, $dimension = 2)
70
    {
71 1
        if (null === $keys) {
72 1
            return $array;
73
        }
74 1
        $result = [];
75 1
        if (2 === $dimension) {
76 1
            foreach ($array as $k => $row) {
77 1
                foreach ($keys as $key) {
78 1
                    if (array_key_exists($key, $row)) {
79 1
                        $result[$k][$key] = I::get($row, $key);
80
                    } else {
81 1
                        $result[$k][$key] = null;
82
                    }
83
                }
84
            }
85
        }
86 1
        if (1 === $dimension) {
87 1
            foreach ($array as $k => $row) {
88 1
                if (in_array($k, $keys, true)) {
89 1
                    $result[$k] = $row;
90
                } else {
91 1
                    $result[$k] = null;
92
                }
93
            }
94
        }
95
96 1
        return $result;
97
    }
98
99
    /**
100
     * 返回二维(或者更高)数组中指定键的一列的所有值
101
     *
102
     * - array_column 要求 PHP >= 5.5,这个是兼容 5.5 以下的
103
     * - 如果需要取某几项,使用 Arrays::columns
104
     * - 简单理解就是:从数据库里查出来几条数据,只要其中某个属性的所有值
105
     * - USE_CUSTOM
106
     *
107
     * @see http://php.net/array_column
108
     *
109
     * @param array $array
110
     * @param string $column 需要被取出来的字段
111
     * @param string $index 作为 index 的字段
112
     *
113
     * @return array
114
     *
115
     * @tested
116
     */
117 1
    public static function column($array, $column, $index = null)
118
    {
119 1
        if (function_exists('array_column') && false === I::ini('USE_CUSTOM')) {
120 1
            return array_column($array, $column, $index);
121
        } else {
122 1
            $result = [];
123 1
            foreach ($array as $row) {
124 1
                $data = I::get($row, $column);
125 1
                if (null === $index) {
126 1
                    $result[] = $data;
127
                } else {
128 1
                    $result[$row[$index]] = $data;
129
                }
130
            }
131
132 1
            return $result;
133
        }
134
    }
135
136
    /**
137
     * 创建一个数组,用一个数组的值作为其键名,另一个数组的值作为其值
138
     *
139
     * - array_combine:两个数组元素个数不一致将报错
140
     * - 在两个数组元素个数不一致时,以键为准:
141
     *      1.键比值多,值都被填充为 null
142
     *      2.值比键多,值被舍去
143
     * ```
144
     *
145
     * @see http://php.net/array_combine
146
     *
147
     * @param array $keys
148
     * @param array $values
149
     *
150
     * @return array
151
     *
152
     * @tested
153
     */
154 2
    public static function combine($keys, $values)
155
    {
156 2
        if (count($keys) == count($values)) {
157 2
            return (array) array_combine($keys, $values);
158
        }
159 1
        $array = [];
160 1
        foreach ($keys as $index => $key) {
161 1
            $array[$key] = I::get($values, $index);
162
        }
163 1
        return $array;
164
    }
165
166
    /**
167
     * 递归地合并多个数组
168
     *
169
     * - array_merge_recursive:如果有相同的键,后者会覆盖前者
170
     * - 此函数会合并两个相同键的值到一个数组里
171
     *
172
     * @see http://php.net/array_merge_recursive
173
     *
174
     * @param array $a 数组1
175
     * @param array $b 数组2(可以任意个数组)
176
     *
177
     * @return array
178
     *
179
     * @tested
180
     */
181 38
    public static function merge($a, $b)
182
    {
183 38
        $args = func_get_args();
184 38
        $res = array_shift($args);
185 38
        while (!empty($args)) {
186 38
            foreach (array_shift($args) as $k => $v) {
187 3
                if (is_int($k)) {
188 2
                    if (array_key_exists($k, $res)) {
189 2
                        $res[] = $v;
190
                    } else {
191 2
                        $res[$k] = $v;
192
                    }
193 2
                } elseif (is_array($v) && isset($res[$k]) && is_array($res[$k])) {
194 1
                    $res[$k] = self::merge($res[$k], $v);
195
                } else {
196 2
                    $res[$k] = $v;
197
                }
198
            }
199
        }
200
201 38
        return $res;
202
    }
203
204
    /**
205
     *  range 的性能优化版
206
     *
207
     * @see http://php.net/manual/zh/language.generators.overview.php
208
     * @version PHP >= 5.5
209
     *
210
     * @param integer $start 开始
211
     * @param integer $end 结束
212
     * @param integer $step 步长
213
     *
214
     * @return \Generator
215
     *
216
     * @tested
217
     */
218 5
    public static function rangeGenerator($start, $end, $step = 1)
219
    {
220 5
        if ($start < $end) {
221 4
            C::assertTrue($step > 0, '步长必须大于 0');
222 4
            for ($i = $start; $i <= $end; $i += $step) {
223 4
                yield $i;
224
            }
225 2
        } elseif ($start > $end) {
226 1
            C::assertTrue($step < 0, '步长必须小于 0');
227 1
            for ($i = $start; $i >= $end; $i += $step) {
228 1
                yield $i;
229
            }
230
        } else {
231 1
            yield $start;
232
        }
233 5
    }
234
235
    /**
236
     * 找到符合条件的第一项
237
     *
238
     * @param array $array
239
     * @param callback $callback 条件回调,结果为 true 的第一项会被取出
240
     *
241
     * @return mixed
242
     *
243
     * @tested
244
     */
245 1
    public static function detectFirst($array, $callback)
246
    {
247 1
        foreach ($array as $key => $item) {
248 1
            if (true === I::call($callback, [$item, $key])) {
249 1
                return $item;
250
            }
251
        }
252 1
        return null;
253
    }
254
255
    /**
256
     * 找到符合条件的所有项
257
     *
258
     * @param array $array
259
     * @param callback $callback 条件回调,结果为 true 的所有项会被取出
260
     * @param callback $filter 对符合条件的项进行回调处理并返回
261
     *
262
     * @return array
263
     *
264
     * @tested
265
     */
266 1
    public static function detectAll($array, $callback, $filter = null)
267
    {
268 1
        $all = [];
269 1
        foreach ($array as $key => $item) {
270 1
            if (true === I::call($callback, [$item, $key])) {
271 1
                if (null !== $filter) {
272 1
                    $all[$key] = I::call($filter, [$item, $key]);
273
                } else {
274 1
                    $all[$key] = $item;
275
                }
276
            }
277
        }
278 1
        return $all;
279
    }
280
281
    /**
282
     * 返回数组的最后一个元素的键
283
     *
284
     * - array_key_last:需要 PHP7.3.0+ 才能支持
285
     * - USE_CUSTOM
286
     *
287
     * @param array $array
288
     *
289
     * @return string|null
290
     *
291
     * @tested
292
     */
293 1
    public static function keyLast($array)
294
    {
295 1
        if (!is_array($array) || empty($array)) {
296 1
            return null;
297
        }
298 1
        if (function_exists('array_key_last') && false === I::ini('USE_CUSTOM')) {
299 1
            return array_key_last($array);
300
        }
301 1
        end($array);
302 1
        return key($array);
303
    }
304
305
    /**
306
     * 返回数组的第一个元素的键
307
     *
308
     * - array_key_first:需要 PHP7.3.0+ 才能支持
309
     * - USE_CUSTOM
310
     *
311
     * @param array $array
312
     *
313
     * @return string|null
314
     *
315
     * @tested
316
     */
317 1
    public static function keyFirst($array)
318
    {
319 1
        if (!is_array($array) || empty($array)) {
320 1
            return null;
321
        }
322 1
        if (function_exists('array_key_first') && false === I::ini('USE_CUSTOM')) {
323 1
            return array_key_first($array);
324
        }
325 1
        reset($array);
326 1
        return key($array);
327
    }
328
329
    /**
330
     * 获取数组的维度
331
     *
332
     * @param array $array 多维数组
333
     *
334
     * @return integer
335
     *
336
     * @tested
337
     */
338 1
    public static function dimension($array)
339
    {
340 1
        if (!is_array($array)) {
341 1
            return 0;
342
        }
343 1
        $max = 1;
344 1
        foreach ($array as $value) {
345 1
            if (is_array($value)) {
346 1
                $d = self::dimension($value) + 1;
347 1
                if ($d > $max) {
348 1
                    $max = $d;
349
                }
350
            }
351
        }
352 1
        return $max;
353
    }
354
355
    /**
356
     * 判断数组是不是关联数组
357
     *
358
     * @param array $array
359
     *
360
     * @return boolean
361
     *
362
     * @tested
363
     */
364 1
    public static function isAssoc($array)
365
    {
366 1
        if (is_array($array)) {
367 1
            $keys = array_keys($array);
368 1
            return $keys !== array_keys($keys);
369
        }
370 1
        return false;
371
    }
372
373
    /**
374
     * 判断数组是不是索引数组
375
     *
376
     * 索引数组必须是下标从 0 开始的数组,键是数字还是字符串类型的数字无所谓
377
     *
378
     * @param array $array
379
     *
380
     * @return boolean
381
     *
382
     * @tested
383
     */
384 1
    public static function isIndexed($array)
385
    {
386 1
        if (is_array($array)) {
387 1
            $keys = array_keys($array);
388 1
            return $keys === array_keys($keys);
389
        }
390 1
        return false;
391
    }
392
393
    /**
394
     * 返回数组的顺数第 n 个元素,其中 n >= 1 且为整数,空数组直接返回 null
395
     *
396
     * - 支持关联数组,超过数组长度会对数组长度求余后查找
397
     *
398
     * @param array $array
399
     * @param int $pos 顺数第 n 个,默认 1
400
     *
401
     * @return mixed
402
     *
403
     * @tested
404
     */
405 2
    public static function first($array, $pos = 1)
406
    {
407 2
        if (0 === ($count = self::count($array))) {
408 1
            return null;
409
        }
410 2
        $p = $pos % $count;
411 2
        if (0 === $p) {
412 1
            $p = $count;
413
        }
414 2
        for ($i = 1; $i < $p; $i++) {
415 1
            next($array);
416
        }
417 2
        return current($array);
418
    }
419
420
    /**
421
     * 返回数组的倒数第 n 个元素,其中 n >= 1 且为整数,空数组直接返回 null
422
     *
423
     * - 支持关联数组,超过数组长度会对数组长度求余后查找
424
     *
425
     * @param array $array
426
     * @param int $pos 倒数第 n 个,默认 1
427
     *
428
     * @return mixed
429
     *
430
     * @tested
431
     */
432 1
    public static function last($array, $pos = 1)
433
    {
434 1
        if (0 === ($count = self::count($array))) {
435 1
            return null;
436
        }
437 1
        $p = $pos % $count;
438 1
        if (0 === $p) {
439 1
            $p = $count;
440
        }
441 1
        end($array);
442 1
        for ($i = 1; $i < $p; $i++) {
443 1
            prev($array);
444
        }
445 1
        return current($array);
446
    }
447
448
    /**
449
     * 计算数组中的单元数目
450
     *
451
     * - count:在非数组情况下,除了 null 会返回 0,其他都返回 1,囧
452
     * - $callback 参数用于对符合条件的项做筛选
453
     *
454
     * @param array|mixed $array 数组
455
     * @param callback|mixed $callback 回调,返回回调值为 true 的项,如果此参数是非回调类型,表示查询和此值严格相等的项
456
     * @param boolean $isStrict 是否为严格模式,如果为 false,回调值为 true 值的也会返回,为字符串时不使用严格比较
457
     *
458
     * @return integer
459
     *
460
     * @tested
461
     */
462 9
    public static function count($array, $callback = null, $isStrict = true)
463
    {
464 9
        $count = 0;
465 9
        if (is_array($array)) {
466 9
            if (null === $callback) {
467 9
                return count($array);
468
            } else {
469 2
                $function = $callback;
470 2
                if (false === is_callable($callback)) {
471
                    $function = function ($row) use ($callback, $isStrict) {
472 2
                        return true === $isStrict ? $row === $callback : $row == $callback;
473 2
                    };
474
                }
475 2
                foreach ($array as $key => $row) {
476 2
                    if (true === I::call($function, [$row, $key])) {
477 2
                        $count++;
478
                    }
479
                }
480
481
            }
482
        }
483 2
        return $count;
484
    }
485
486
    /**
487
     * 返回指定长度的数组,不足的值设置为 null
488
     *
489
     * @param array $array
490
     * @param integer $count 指定长度
491
     * @param callback $callback 回调参数:数组的值、数组的键
492
     *
493
     * @return array
494
     *
495
     * @tested
496
     */
497 2
    public static function lists($array, $count = null, $callback = null)
498
    {
499 2
        null === $count && $count = self::count($array);
500 2
        $arrayCount = self::count($array);
501 2
        if ($arrayCount >= $count) {
502 2
            $return = $array;
503
        } else {
504 1
            $return = self::merge($array, self::fill(0, $count - $arrayCount, null));
505
        }
506 2
        if (null !== $callback) {
507 1
            foreach ($return as $key => $value) {
508 1
                $return[$key] = I::call($callback, [$value, $key]);
509
            }
510
        }
511 2
        return $return;
512
    }
513
514
    /**
515
     * 获取指定某些键的项的值
516
     *
517
     * @param array $array
518
     * @param array|string $keys 数组或逗号字符串
519
     *
520
     * @return array
521
     *
522
     * @tested
523
     */
524 1
    public static function values($array, $keys = null)
525
    {
526 1
        return array_values(self::some($array, $keys));
527
    }
528
529
    /**
530
     * 获取指定某些键的项
531
     *
532
     * @param array $array
533
     * @param array|string $keys 数组或都好字符串
534
     *
535
     * @return array
536
     *
537
     * @tested
538
     */
539 2
    public static function some($array, $keys = null)
540
    {
541 2
        if (null === $keys) {
542 1
            return $array;
543
        }
544 2
        $keys = Strings::toArray($keys);
545 2
        return array_intersect_key($array, array_flip($keys));
546
    }
547
548
    /**
549
     * 获取指定除了某些键的项
550
     *
551
     * @param array $array
552
     * @param array|string $keys
553
     *
554
     * @return array
555
     *
556
     * @tested
557
     */
558 1
    public static function exceptedKeys($array, $keys)
559
    {
560 1
        $keys = Strings::toArray($keys);
561 1
        return array_diff_key($array, array_flip($keys));
562
    }
563
564
    /**
565
     * 检查数组里是否有指定的所有键名或索引
566
     *
567
     * - array_key_exists:检测一个指定的键
568
     * - Arrays::keyExistsOne:检测数组里是否存在指定的某些键
569
     *
570
     * @param array $keys 要检查的键
571
     * @param array $array
572
     * @param array $diff 引用返回不包含的键
573
     *
574
     * @return boolean
575
     *
576
     * @tested
577
     */
578 1
    public static function keyExistsAll($keys, $array, &$diff = null)
579
    {
580
581 1
        return I::isEmpty($diff = array_diff($keys, array_keys($array)));
582
    }
583
584
    /**
585
     * 检查数组里是否有指定的某些键名或索引
586
     *
587
     * @param array $keys 要检查的键
588
     * @param array $array
589
     * @param array $find 引用返回包含的键
590
     *
591
     * @return boolean
592
     *
593
     * @tested
594
     */
595 1
    public static function keyExistsSome($keys, $array, &$find = null)
596
    {
597 1
        return !I::isEmpty($find = array_intersect($keys, array_keys($array)));
598
    }
599
600
    /**
601
     * 检查数组里是否有指定的所有值
602
     *
603
     * @param array $values 要检查的值
604
     * @param array $array
605
     * @param array $diff 引用返回不包含的值
606
     *
607
     * @return boolean
608
     *
609
     * @tested
610
     */
611 1
    public static function valueExistsAll($values, $array, &$diff = null)
612
    {
613 1
        return I::isEmpty($diff = array_diff($values, array_values($array)));
614
    }
615
616
    /**
617
     * 检查数组里是否有指定的某些值
618
     *
619
     * @param array $values 要检查的值
620
     * @param array $array
621
     * @param array $find 引用返回包含的值
622
     *
623
     * @return boolean
624
     *
625
     * @tested
626
     */
627 1
    public static function valueExistsSome($values, $array, &$find = null)
628
    {
629 1
        return !I::isEmpty($find = array_intersect($values, array_values($array)));
630
    }
631
632
    /**
633
     * 参照 PHP 的 array_combine 函数,array_combine 得到的是一行记录的格式,该函数得到多行
634
     *
635
     * - arrays 里的每个数组会和 keys 使用 self::combine 合并,最终合并成为一个二维数组
636
     *
637
     * @param array $keys 作为键的字段
638
     * @param array $arrays
639
     *
640
     * @return array
641
     *
642
     * @tested
643
     */
644 1
    public static function combines($keys, $arrays)
645
    {
646 1
        $result = [];
647 1
        foreach ($arrays as $k => $array) {
648 1
            $result[$k] = self::combine($keys, $array);
649
        }
650
651 1
        return $result;
652
    }
653
654
    /**
655
     * 把数组里逗号字符串拆分,并且去掉重复的部分
656
     *
657
     * @param array $array
658
     *
659
     * @return array
660
     *
661
     * @tested
662
     */
663 2
    public static function toPart($array)
664
    {
665 2
        return array_values(
666 2
            array_filter(
667 2
                array_keys(
668 2
                    array_flip(
669 2
                        explode(',', implode(',', $array))
670
                    )
671
                )
672
            )
673
        );
674
    }
675
676
    /**
677
     * 矩阵转置
678
     *
679
     * @param array $array 待转置的矩阵
680
     *
681
     * @return array
682
     *
683
     * @tested
684
     */
685 1
    public static function transposed($array)
686
    {
687 1
        $data = [];
688 1
        foreach ($array as $r => $row) {
689 1
            foreach ($row as $c => $col) {
690 1
                $data[$c][$r] = $col;
691
            }
692
        }
693 1
        return $data;
694
    }
695
696
    /**
697
     * 普通二维数组转化成 Excel 单元格二维数组
698
     *
699
     * @param array $array
700
     *
701
     * @return array
702
     *
703
     * @tested
704
     */
705 1
    public static function toCellArray($array)
706
    {
707 1
        $data = [];
708 1
        $rowIndex = 0;
709 1
        foreach ($array as $row) {
710 1
            $rowIndex++;
711 1
            $colIndex = 'A';
712 1
            foreach ($row as $col) {
713 1
                $data[$rowIndex][$colIndex++] = $col;
714
            }
715
        }
716 1
        return $data;
717
    }
718
719
    /**
720
     * 返回矩阵的列数和行数
721
     *
722
     * - 返回两个元素的一维数组,第一个元素表示矩阵的列数,第二个元素表示矩阵的行数
723
     *
724
     * @param array $array
725
     *
726
     * @return array
727
     *
728
     * @tested
729
     */
730 1
    public static function colRowCount($array)
731
    {
732 1
        return [self::count(self::first($array)), self::count($array)];
733
    }
734
735
    /**
736
     * 用给定的值填充数组
737
     *
738
     * - array_fill:第一参数在为负的时候,生成的数组的第二个元素是从 0 开始的!
739
     *
740
     * @param int $startIndex 返回的数组的第一个索引值
741
     * @param int $num 插入元素的数量。如果为 0 或者负数,则返回空数组
742
     * @param mixed $value 用来填充的值
743
     *
744
     * @return array
745
     *
746
     * @tested
747
     */
748 2
    public static function fill($startIndex, $num, $value)
749
    {
750 2
        if ($num <= 0) {
751 1
            return [];
752
        }
753 2
        $array = [];
754 2
        foreach (self::rangeGenerator($startIndex, $startIndex + $num - 1) as $key) {
755 2
            $array[$key] = $value;
756
        }
757 2
        return $array;
758
    }
759
760
    /**
761
     * 让 var_export 返回 `[]` 的格式
762
     *
763
     * @param mixed $expression 变量
764
     * @param bool $return 默认值 为 true,即返回字符串而不是输出
765
     *
766
     * @return mixed
767
     *
768
     * @tested
769
     */
770 1
    public static function export($expression, $return = true)
771
    {
772 1
        $export = var_export($expression, true);
773 1
        $export = preg_replace("/^([ ]*)(.*)/m", '$1$1$2', $export);
774 1
        $array = preg_split("/\r\n|\n|\r/", $export);
775 1
        $array = preg_replace(["/\s*array\s\($/", "/\)(,)?$/", "/\s=>\s$/"], [null, ']$1', ' => ['], $array);
776 1
        $export = implode(PHP_EOL, array_filter(["["] + $array));
777 1
        if (true === $return) {
778 1
            return $export;
779
        } else {
780 1
            echo $export;
781
        }
782 1
    }
783
784
    /**
785
     * 将 CSV 文本转成数组
786
     *
787
     * @param string $csvString
788
     *
789
     * @return array
790
     *
791
     * @tested
792
     */
793 1
    public static function fromCsv($csvString)
794
    {
795 1
        $lines = explode(PHP_EOL, $csvString);
796 1
        $array = [];
797 1
        foreach ($lines as $line) {
798 1
            $array[] = explode(',', $line);
799
        }
800 1
        return $array;
801
    }
802
803
    /**
804
     * 在数组中搜索给定的值,如果成功则返回首个相应的键名
805
     *
806
     * - 第一参数如果不是回调函数,则此方法等同于 array_search
807
     * - 第一参数如果是回调函数,则找到的条件为:回调值为 true
808
     * - 第三参数如果是 false,则回调值只需要 true 值即可(例如:1)
809
     *
810
     * @param mixed|callback $search 搜索的值
811
     * @param array $array 这个数组
812
     * @param boolean $isStrict 是否检查完全相同的元素
813
     *
814
     * @return mixed|false
815
     *
816
     * @tested
817
     */
818 1
    public static function search($search, $array, $isStrict = false)
819
    {
820 1
        if (false === is_callable($search)) {
821 1
            return array_search($search, $array, $isStrict);
822
        }
823 1
        foreach ($array as $key => $row) {
824 1
            $result = I::call($search, [$row]);
825 1
            if ((true === $isStrict && true === $result) || (false === $isStrict && true == $result)) {
826 1
                return $key;
827
            }
828
        }
829 1
        return false;
830
    }
831
832
    /**
833
     * 递增数组的一个值并返回
834
     *
835
     * - 如果该值不存在,则默认为 0
836
     *
837
     * @param array $array 引用返回数组
838
     * @param string $key
839
     * @param integer $step 步长,默认 1
840
     *
841
     * @return double|integer
842
     *
843
     * @tested
844
     */
845 1
    public static function increment(&$array, $key, $step = 1)
846
    {
847 1
        $array[$key] = I::get($array, $key, 0) + $step;
848 1
        return $array[$key];
849
    }
850
851
    /**
852
     * 递减数组的一个值并返回
853
     *
854
     * - 如果该值不存在,则默认为 0
855
     *
856
     * @param array $array 引用返回数组
857
     * @param string $key
858
     * @param integer $step 步长,默认 1
859
     *
860
     * @return double|integer
861
     *
862
     * @tested
863
     */
864 1
    public static function decrement(&$array, $key, $step = 1)
865
    {
866 1
        $array[$key] = I::get($array, $key, 0) - $step;
867 1
        return $array[$key];
868
    }
869
870
    /**
871
     * in_array 的扩展
872
     *
873
     * @param mixed $value
874
     * @param array|mixed $array
875
     * @param boolean $isStrict 是否严格匹配,默认 false,即不严格
876
     * @param boolean $ignoreCase 是否忽略大小写,默认 false,不忽略
877
     *
878
     * @return boolean
879
     */
880 3
    public static function in($value, $array, $isStrict = false, $ignoreCase = false)
881
    {
882 3
        if (false === is_array($array)) {
883 1
            return false;
884
        }
885 3
        if (false === $ignoreCase) {
886 1
            return in_array($value, $array, $isStrict);
887
        } else {
888 3
            $value = Json::decode(strtolower(Json::encode($value)));
889 3
            $array = Json::decode(strtolower(Json::encode($array)));
890 3
            return in_array($value, $array, $isStrict);
891
        }
892
    }
893
894
    /**
895
     * 对一个数组执行回调并返回新数组
896
     *
897
     * @param array|mixed $array
898
     * @param callback $valueCallback 对值的回调
899
     * @param callback|null $keyCallback 对键的回调
900
     *
901
     * @return array
902
     */
903
    public static function map($array, $valueCallback, $keyCallback = null)
904
    {
905
        $return = [];
906
        if (is_array($array)) {
907
            foreach ($array as $key => $value) {
908
                $callValue = I::call($valueCallback, [$value, $key]);
909
                $callKey = null === $keyCallback ? $key : I::call($keyCallback, [$value, $key]);
910
                $return[$callKey] = $callValue;
911
            }
912
        }
913
        return $return;
914
    }
915
916
    /**
917
     * 排队取号
918
     *
919
     * - 含义:给定只包含数字的索引数组,索引数组的值作为号码从小到大排序,如果中间漏掉某个号码,则返回该号码,否则返回最后一位号码,并且引用返回该队列
920
     * - 号码的值从 0 开始
921
     * - 例子:[4, 0, 1] 将引用返回数组[4, 0, 1, 2],函数返回 2
922
     *
923
     * @param array $array
924
     * @param integer $begin 开始的号码,默认为 0
925
     *
926
     * @return integer
927
     */
928
    public static function queueNumber(&$array, $begin = 0)
929
    {
930
        $array2 = $array;
931
        sort($array2);
932
        $next = $begin;
933
        foreach ($array2 as $v) {
934
            if ($v > $next) {
935
                break;
936
            } elseif ($v < $next) {
937
                if ($v + 1 > $next) {
938
                    $next = $v + 1;
939
                }
940
            } else {
941
                $next++;
942
            }
943
        }
944
        array_push($array, $next);
945
        return $next;
946
    }
947
948
}
949