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.
Passed
Pull Request — master (#28)
by t
02:46 queued 27s
created

Arrays::columns1()   A

Complexity

Conditions 1
Paths 1

Size

Total Lines 3
Code Lines 1

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 0
CRAP Score 2

Importance

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