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
Push — master ( 6d880e...6fcb7a )
by t
05:21 queued 03:08
created

Arrays   F

Complexity

Total Complexity 126

Size/Duplication

Total Lines 923
Duplicated Lines 0 %

Test Coverage

Coverage 92.13%

Importance

Changes 25
Bugs 2 Features 0
Metric Value
eloc 242
dl 0
loc 923
ccs 246
cts 267
cp 0.9213
rs 2
c 25
b 2
f 0
wmc 126

38 Methods

Rating   Name   Duplication   Size   Complexity  
A combine() 0 10 3
A indexBy() 0 15 4
B merge() 0 21 8
B columns() 0 28 9
A column() 0 16 5
A transposed() 0 9 3
B count() 0 22 7
B search() 0 12 7
A toPart() 0 7 1
A detectFirst() 0 8 3
A dimension() 0 15 5
A keyFirst() 0 10 5
A toCellArray() 0 12 3
A decrement() 0 4 1
A valueExistsAll() 0 3 1
A rangeGenerator() 0 14 5
A lists() 0 15 5
A export() 0 11 2
A isIndexed() 0 7 2
A last() 0 14 4
A combines() 0 8 2
A keyExistsAll() 0 4 1
A fill() 0 10 3
A first() 0 13 4
A some() 0 7 2
A increment() 0 4 1
A values() 0 3 1
A fromCsv() 0 8 2
A isAssoc() 0 7 2
A exceptedKeys() 0 4 1
A valueExistsSome() 0 3 1
A colRowCount() 0 3 1
A keyExistsSome() 0 3 1
A in() 0 11 3
A detectAll() 0 13 4
A keyLast() 0 10 5
A map() 0 11 4
A queueNumber() 0 18 5

How to fix   Complexity   

Complex Class

Complex classes like Arrays often do a lot of different things. To break such a class down, we need to identify a cohesive component within that class. A common approach to find such a component is to look for fields/methods that share the same prefixes, or suffixes.

Once you have determined the fields that belong together, you can apply the Extract Class refactoring. If the component makes sense as a sub-class, Extract Subclass is also a candidate, and is often faster.

While breaking up the class, it is a good idea to analyze how other classes use Arrays, and based on these observations, apply Extract Interface, too.

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