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.
Failed Conditions
Pull Request — master (#10)
by
unknown
02:51
created

src/collection_functions.php (2 issues)

Upgrade to new PHP Analysis Engine

These results are based on our legacy PHP analysis, consider migrating to our new PHP analysis engine instead. Learn more

1
<?php
2
3
namespace DusanKasan\Knapsack;
4
5
use ArrayIterator;
6
use DusanKasan\Knapsack\Exceptions\ItemNotFound;
7
use DusanKasan\Knapsack\Exceptions\NoMoreItems;
8
use Traversable;
9
10
/**
11
 * Converts $collection to array. If $collection is not array or Traversable, an array [$collection] will be returned.
12
 * If there are multiple items with the same key, only the last will be preserved.
13
 *
14
 * @param array|Traversable $collection
15
 * @return array
16
 */
17
function toArray($collection)
18
{
19 53
    $arr = [];
20 53
    foreach ($collection as $key => $value) {
21 53
        $arr[$key] = $value;
22 53
    }
23
24 53
    return $arr;
25
}
26
27
/**
28
 * Returns a lazy collection of distinct items in $collection.
29
 *
30
 * @param array|Traversable $collection
31
 * @return Collection
32
 */
33
function distinct($collection)
34
{
35
    $generatorFactory = function () use ($collection) {
36 1
        $distinctValues = [];
37
38 1
        foreach ($collection as $key => $value) {
39 1
            if (!in_array($value, $distinctValues)) {
40 1
                $distinctValues[] = $value;
41 1
                yield $key => $value;
42 1
            }
43 1
        }
44 1
    };
45
46 1
    return new Collection($generatorFactory);
47
}
48
49
/**
50
 * Returns number of items in $collection.
51
 *
52
 * @param array|Traversable $collection
53
 * @return int
54
 */
55
function size($collection)
56
{
57 8
    $result = 0;
58 8
    foreach ($collection as $value) {
59 8
        $result++;
60 8
    }
61
62 8
    return $result;
63
}
64
65
/**
66
 * Returns a non-lazy collection with items from $collection in reversed order.
67
 *
68
 * @param array|Traversable $collection
69
 * @return Collection
70
 */
71
function reverse($collection)
72
{
73
    $generatorFactory = function () use ($collection) {
74 4
        $array = [];
75 4
        foreach ($collection as $key => $value) {
76 3
            $array[] = [$key, $value];
77 4
        }
78
79 5
        return map(
80 4
            indexBy(
81 4
                array_reverse($array),
82
                function($item) {
83 3
                    return $item[0];
84
                }
85 4
            ),
86
            function($item) {
87 3
                return $item[1];
88
            }
89 4
        );
90 4
    };
91
92 4
    return new Collection($generatorFactory);
93
}
94
95
/**
96
 * Returns a lazy collection of values from $collection (i.e. the keys are reset).
97
 *
98
 * @param array|Traversable $collection
99
 * @return Collection
100
 */
101
function values($collection)
102
{
103
    $generatorFactory = function () use ($collection) {
104 23
        foreach ($collection as $value) {
105 21
            yield $value;
106 18
        }
107 23
    };
108
109 23
    return new Collection($generatorFactory);
110
}
111
112
/**
113
 * Returns a lazy collection of keys from $collection.
114
 *
115
 * @param array|Traversable $collection
116
 * @return Collection
117
 */
118
function keys($collection)
119
{
120
    $generatorFactory = function () use ($collection) {
121 1
        foreach ($collection as $key => $value) {
122 1
            yield $key;
123 1
        }
124 1
    };
125
126 1
    return new Collection($generatorFactory);
127
}
128
129
/**
130
 * Returns a lazy collection of items from $collection repeated infinitely.
131
 *
132
 * @param array|Traversable $collection
133
 * @return Collection
134
 */
135
function cycle($collection)
136
{
137
    $generatorFactory = function () use ($collection) {
138 1
        while (true) {
139 1
            foreach ($collection as $key => $value) {
140 1
                yield $key => $value;
141 1
            }
142 1
        }
143 1
    };
144
145 1
    return new Collection($generatorFactory);
146
}
147
148
/**
149
 * Returns a non-lazy collection of shuffled items from $collection.
150
 *
151
 * @param array|Traversable $collection
152
 * @return Collection
153
 */
154
function shuffle($collection)
155
{
156 1
    $buffer = [];
157 1
    foreach ($collection as $key => $value) {
158 1
        $buffer[] = [$key, $value];
159 1
    }
160
161 1
    \shuffle($buffer);
162
163 1
    return dereferenceKeyValue($buffer);
164
}
165
166
/**
167
 * Returns true if $collection does not contain any items.
168
 *
169
 * @param array|Traversable $collection
170
 * @return bool
171
 */
172
function isEmpty($collection)
173
{
174 2
    foreach ($collection as $value) {
175 1
        return false;
176 1
    }
177
178 1
    return true;
179
}
180
181
/**
182
 * Returns true if $collection does contain any items.
183
 *
184
 * @param array|Traversable $collection
185
 * @return bool
186
 */
187
function isNotEmpty($collection)
188
{
189 2
    return !isEmpty($collection);
190
}
191
192
/**
193
 * Returns a collection where keys are distinct values from $collection and values are number of occurrences of each
194
 * value.
195
 *
196
 * @param array|Traversable $collection
197
 * @return Collection
198
 */
199
function frequencies($collection)
200
{
201 1
    return countBy($collection, '\DusanKasan\Knapsack\identity');
202
}
203
204
/**
205
 * Returns the first item of $collection or throws ItemNotFound if #collection is empty.
206
 *
207
 * @param array|Traversable $collection
208
 * @return mixed
209
 */
210
function first($collection)
211
{
212 12
    return getNth($collection, 0);
213
}
214
215
/**
216
 * Returns the last item of $collection or throws ItemNotFound if #collection is empty.
217
 *
218
 * @param array|Traversable $collection
219
 * @return mixed
220
 */
221
function last($collection)
222
{
223 2
    return first(reverse($collection));
224
}
225
226
/**
227
 * Returns a lazy collection of items of $collection where value of each item is set to the return value of calling
228
 * $function on its value and key.
229
 *
230
 * @param array|Traversable $collection
231
 * @param callable $function ($value, $key)
232
 * @return Collection
233
 */
234 View Code Duplication
function map($collection, callable $function)
235
{
236
    $generatorFactory = function () use ($collection, $function) {
237 10
        foreach ($collection as $key => $value) {
238 9
            yield $key => $function($value, $key);
239 9
        }
240 10
    };
241
242 10
    return new Collection($generatorFactory);
243
}
244
245
/**
246
 * Returns a lazy collection of items from $collection for which $function returns true.
247
 *
248
 * @param array|Traversable $collection
249
 * @param callable $function ($value, $key)
250
 * @return Collection
251
 */
252 View Code Duplication
function filter($collection, callable $function)
253
{
254
    $generatorFactory = function () use ($collection, $function) {
255 2
        foreach ($collection as $key => $value) {
256 2
            if ($function($value, $key)) {
257 2
                yield $key => $value;
258 2
            }
259 2
        }
260 2
    };
261
262 2
    return new Collection($generatorFactory);
263
}
264
265
/**
266
 * Returns a lazy collection with items from all $collections passed as argument appended together
267
 *
268
 * @param array|Traversable ...$collections
269
 * @return Collection
270
 */
271
function concat(...$collections)
272
{
273
    $generatorFactory = function () use ($collections) {
274 2
        foreach ($collections as $collection) {
275 2
            foreach ($collection as $key => $value) {
276 2
                yield $key => $value;
277 2
            }
278 2
        }
279 2
    };
280
281 2
    return new Collection($generatorFactory);
282
}
283
284
/**
285
 * Reduces the collection to single value by iterating over the collection and calling $reduction while
286
 * passing $startValue and current key/item as parameters. The output of $function is used as $startValue in
287
 * next iteration. The output of $function on last element is the return value of this function.
288
 *
289
 * @param array|Traversable $collection
290
 * @param callable $function ($value, $key)
291
 * @param mixed $startValue
292
 * @return mixed
293
 */
294
function reduce($collection, callable $function, $startValue)
295
{
296 3
    $tmp = duplicate($startValue);
297
298 3
    foreach ($collection as $key => $value) {
299 3
        $tmp = $function($tmp, $value, $key);
300 3
    }
301
302 3
    return $tmp;
303
}
304
305
/**
306
 * Flattens multiple levels of nesting in collection. If $levelsToFlatten is not specified, flattens all levels of
307
 * nesting.
308
 *
309
 * @param array|Traversable $collection
310
 * @param int $levelsToFlatten -1 to flatten everything
311
 * @return Collection
312
 */
313
function flatten($collection, $levelsToFlatten = -1)
314
{
315
    $generatorFactory = function () use ($collection, $levelsToFlatten) {
316 2
        $flattenNextLevel = $levelsToFlatten < 0 || $levelsToFlatten > 0;
317 2
        $childLevelsToFlatten = $levelsToFlatten > 0 ? $levelsToFlatten - 1 : $levelsToFlatten;
318
319 2
        foreach ($collection as $key => $value) {
320 2
            if ($flattenNextLevel && (is_array($value) || $value instanceof Traversable)) {
321 2
                foreach (flatten($value, $childLevelsToFlatten) as $childKey => $childValue) {
322 2
                    yield $childKey => $childValue;
323 2
                }
324 2
            } else {
325 2
                yield $key => $value;
326
            }
327 2
        }
328 2
    };
329
330 2
    return new Collection($generatorFactory);
331
}
332
333
/**
334
 * Returns a non-lazy collection sorted using $collection($item1, $item2, $key1, $key2 ). $collection should
335
 * return true if first item is larger than the second and false otherwise.
336
 *
337
 * @param array|Traversable $collection
338
 * @param callable $function ($value1, $value2, $key1, $key2)
339
 * @return Collection
340
 */
341
function sort($collection, callable $function)
342
{
343 1
    $array = iterator_to_array(
344 1
        values(
345 1
            map(
346 1
                $collection,
347
                function ($value, $key) {
348 1
                    return [$key, $value];
349
                }
350 1
            )
351 1
        )
352 1
    );
353
354 1
    uasort(
355 1
        $array,
356
        function ($a, $b) use ($function) {
357 1
            return $function($a[1], $b[1], $a[0], $b[0]);
358
        }
359 1
    );
360
361 1
    return dereferenceKeyValue($array);
362
}
363
364
/**
365
 * Returns a lazy collection that is a part of $collection starting from $from position and ending in $to position.
366
 * If $to is not provided, the returned collection is contains all items from $from until end of $collection. All items
367
 * before $from are iterated over, but not included in result.
368
 *
369
 * @param array|Traversable $collection
370
 * @param int $from
371
 * @param int $to -1 to slice until end
372
 * @return Collection
373
 */
374
function slice($collection, $from, $to = -1)
375
{
376
    $generatorFactory = function () use ($collection, $from, $to) {
377 14
        $index = 0;
378 14
        foreach ($collection as $key => $value) {
379 14
            if ($index >= $from && ($index < $to || $to == -1)) {
380 14
                yield $key => $value;
381 14
            } elseif ($index >= $to && $to >= 0) {
382 11
                break;
383
            }
384
385 14
            $index++;
386 14
        }
387 14
    };
388
389 14
    return new Collection($generatorFactory);
390
}
391
392
/**
393
 * Returns a non-lazy collection of items grouped by the result of $function.
394
 *
395
 * @param array|Traversable $collection
396
 * @param callable $function ($value, $key)
397
 * @return Collection
398
 */
399 View Code Duplication
function groupBy($collection, callable $function)
400
{
401 3
    $result = [];
402
403 3
    foreach ($collection as $key => $value) {
404 3
        $newKey = $function($value, $key);
405
406 3
        $group = isset($result[$newKey]) ? $result[$newKey] : new Collection([]);
407 3
        $result[$newKey] = $group->append($value);
408 3
    }
409
410 3
    return Collection::from($result);
411
}
412
413
/**
414
 * Returns a non-lazy collection of items grouped by the value at given key.
415
 *
416
 * @param array|Traversable $collection
417
 * @param mixed $key
0 ignored issues
show
There is no parameter named $key. Was it maybe removed?

This check looks for PHPDoc comments describing methods or function parameters that do not exist on the corresponding method or function.

Consider the following example. The parameter $italy is not defined by the method finale(...).

/**
 * @param array $germany
 * @param array $island
 * @param array $italy
 */
function finale($germany, $island) {
    return "2:1";
}

The most likely cause is that the parameter was removed, but the annotation was not.

Loading history...
418
 * @return Collection
419
 */
420 View Code Duplication
function groupByKey($collection, $groupKey)
421
{
422 1
    $result = [];
423 1
    $function = getCallable($groupKey);
424
425 1
    foreach ($collection as $key => $value) {
426 1
        $newKey = $function($value, $key);
427
428 1
        $group = isset($result[$newKey]) ? $result[$newKey] : new Collection([]);
429 1
        $result[$newKey] = $group->append($value);
430 1
    }
431
432 1
    return Collection::from($result);
433
}
434
435
/**
436
 * Executes $function for each item in $collection
437
 *
438
 * @param array|Traversable $collection
439
 * @param callable $function ($value, $key)
440
 * @return Collection
441
 */
442 View Code Duplication
function each($collection, callable $function)
443
{
444
    $generatorFactory = function () use ($collection, $function) {
445 1
        foreach ($collection as $key => $value) {
446 1
            $function($value, $key);
447
448 1
            yield $key => $value;
449 1
        }
450 1
    };
451
452 1
    return new Collection($generatorFactory);
453
}
454
455
/**
456
 * Returns an item with $key key from $collection. If that key is not present, throws ItemNotFound.
457
 *
458
 * @param array|Traversable $collection
459
 * @param mixed $key
460
 * @return mixed
461
 */
462
function get($collection, $key)
463
{
464 16
    foreach ($collection as $valueKey => $value) {
465 14
        if ($key === $valueKey) {
466 14
            return $value;
467
        }
468 13
    }
469
470 5
    throw new ItemNotFound;
471
}
472
473
/**
474
 * Returns an item with $key key from $collection. If that key is not present, returns $default.
475
 *
476
 * @param array|Traversable $collection
477
 * @param mixed $key
478
 * @param mixed $default value returned if key is not found
479
 * @return mixed
480
 */
481
function getOrDefault($collection, $key, $default)
482
{
483
    try {
484 2
        return get($collection, $key);
485 2
    } catch (ItemNotFound $e) {
486 2
        return $default;
487
    }
488
}
489
490
/**
491
 * Returns the first item from $collection for which $function returns true. If item like that is not present, returns
492
 * $default.
493
 *
494
 * @param array|Traversable $collection
495
 * @param callable $function ($value, $key)
496
 * @param mixed $default
497
 * @return mixed
498
 */
499
function find($collection, callable $function, $default = null)
500
{
501 1
    foreach ($collection as $key => $value) {
502 1
        if ($function($value, $key)) {
503 1
            return $value;
504
        }
505 1
    }
506
507 1
    return $default;
508
}
509
510
/**
511
 * Returns a lazy collection by changing keys of $collection for each item to the result of $function for
512
 * that item.
513
 *
514
 * @param array|Traversable $collection
515
 * @param callable $function ($value, $key)
516
 * @return Collection
517
 */
518 View Code Duplication
function indexBy($collection, callable $function)
519
{
520
    $generatorFactory = function () use ($collection, $function) {
521 5
        foreach ($collection as $key => $value) {
522 4
            yield $function($value, $key) => $value;
523 4
        }
524 5
    };
525
526 5
    return new Collection($generatorFactory);
527
}
528
529
/**
530
 * Returns a non-lazy collection of items whose keys are the return values of $function and values are the number of
531
 * items in this collection for which the $function returned this value.
532
 *
533
 * @param array|Traversable $collection
534
 * @param callable $function ($value, $key)
535
 * @return Collection
536
 */
537
function countBy($collection, callable $function)
538
{
539 2
    return map(
540 2
        groupBy($collection, $function),
541
        '\DusanKasan\Knapsack\size'
542 2
    );
543
}
544
545
/**
546
 * Returns true if $function returns true for every item in $collection
547
 *
548
 * @param array|Traversable $collection
549
 * @param callable $function ($value, $key)
550
 * @return bool
551
 */
552
function every($collection, callable $function)
553
{
554 1
    foreach ($collection as $key => $value) {
555 1
        if (!$function($value, $key)) {
556 1
            return false;
557
        }
558 1
    }
559
560 1
    return true;
561
}
562
563
/**
564
 * Returns true if $function returns true for at least one item in $collection.
565
 *
566
 * @param array|Traversable $collection
567
 * @param callable $function ($value, $key)
568
 * @return bool
569
 */
570
function some($collection, callable $function)
571
{
572 1
    foreach ($collection as $key => $value) {
573 1
        if ($function($value, $key)) {
574 1
            return true;
575
        }
576 1
    }
577
578 1
    return false;
579
}
580
581
/**
582
 * Returns true if $needle is found in $collection values.
583
 *
584
 * @param $collection
585
 * @param mixed $needle
586
 * @return bool
587
 */
588
function contains($collection, $needle)
589
{
590 1
    foreach ($collection as $key => $value) {
591 1
        if ($value === $needle) {
592 1
            return true;
593
        }
594 1
    }
595
596 1
    return false;
597
}
598
599
/**
600
 * Reduce that walks from right to the left.
601
 *
602
 * @param array|Traversable $collection
603
 * @param callable $function
604
 * @param mixed $startValue
605
 * @return mixed
606
 */
607
function reduceRight($collection, callable $function, $startValue)
608
{
609 1
    return reduce(reverse($collection), $function, $startValue);
610
}
611
612
/**
613
 * Returns a lazy collection of first $numberOfItems items of $collection.
614
 *
615
 * @param array|Traversable $collection
616
 * @param int $numberOfItems
617
 * @return Collection
618
 */
619
function take($collection, $numberOfItems)
620
{
621 11
    return slice($collection, 0, $numberOfItems);
622
}
623
624
/**
625
 * Returns a lazy collection of all but first $numberOfItems items of $collection.
626
 *
627
 * @param array|Traversable $collection
628
 * @param int $numberOfItems
629
 * @return Collection
630
 */
631
function drop($collection, $numberOfItems)
632
{
633 4
    return slice($collection, $numberOfItems);
634
}
635
636
/**
637
 * Returns a lazy collection of values, where first value is $value and all subsequent values are computed by applying
638
 * $function to the last value in the collection. By default this produces an infinite collection. However you can
639
 * end the collection by throwing a NoMoreItems exception.
640
 *
641
 * @param mixed $value
642
 * @param callable $function ($value, $key)
643
 * @return Collection
644
 */
645
function iterate($value, callable $function)
646
{
647 4
    $duplicated = duplicate($value);
648
    $generatorFactory = function () use ($duplicated, $function) {
649 4
        $value = $duplicated;
650
651 4
        yield $value;
652
653 4
        while (true) {
654
            try {
655 4
                $value = $function($value);
656 4
                yield $value;
657 4
            } catch (NoMoreItems $e) {
658 2
                break;
659
            }
660 4
        }
661 4
    };
662
663 4
    return new Collection($generatorFactory);
664
}
665
666
/**
667
 * Returns a lazy collection of items from $collection for which $function returned true.
668
 *
669
 * @param array|Traversable $collection
670
 * @param callable $function ($value, $key)
671
 * @return Collection
672
 */
673
function reject($collection, callable $function)
674
{
675 1
    return filter(
676 1
        $collection,
677
        function($value, $key) use ($function) {
678 1
            return !$function($value, $key);
679
        }
680 1
    );
681
}
682
683
/**
684
 * Returns a lazy collection of items in $collection without the last $numberOfItems items.
685
 *
686
 * @param array|Traversable $collection
687
 * @param int $numberOfItems
688
 * @return Collection
689
 */
690
function dropLast($collection, $numberOfItems = 1)
691
{
692
    $generatorFactory = function () use ($collection, $numberOfItems) {
693 1
        $buffer = [];
694
695 1
        foreach ($collection as $key => $value) {
696 1
            $buffer[] = [$key, $value];
697
698 1
            if (count($buffer) > $numberOfItems) {
699 1
                $val = array_shift($buffer);
700 1
                yield $val[0] => $val[1];
701 1
            }
702 1
        }
703 1
    };
704
705 1
    return new Collection($generatorFactory);
706
}
707
708
/**
709
 * Returns a lazy collection of items from $collection separated by $separator.
710
 *
711
 * @param array|Traversable $collection
712
 * @param mixed $separator
713
 * @return Collection
714
 */
715
function interpose($collection, $separator)
716
{
717
    $generatorFactory = function () use ($collection, $separator) {
718 1
        foreach (take($collection, 1) as $key => $value) {
719 1
            yield $key => $value;
720 1
        }
721
722 1
        foreach (drop($collection, 1) as $key => $value) {
723 1
            yield $separator;
724 1
            yield $key => $value;
725 1
        }
726 1
    };
727
728 1
    return new Collection($generatorFactory);
729
}
730
731
/**
732
 * Returns a lazy collection of first item from first collection, first item from second, second from first and
733
 * so on. Accepts any number of collections.
734
 *
735
 * @param array|Traversable ...$collections
736
 * @return Collection
737
 */
738
function interleave(...$collections)
739
{
740
    $generatorFactory = function () use ($collections) {
741 1
        $normalizedCollection = array_map(
742
            function ($collection) {
743 1
                $c = (is_array($collection)) ? new ArrayIterator($collection) : $collection;
744 1
                $c->rewind();
745 1
                return $c;
746 1
            },
747
            $collections
748 1
        );
749
750
        do {
751 1
            $valid = false;
752 1
            foreach ($normalizedCollection as $collection) {
753 1
                if ($collection->valid()) {
754 1
                    yield $collection->key() => $collection->current();
755 1
                    $collection->next();
756 1
                    $valid = true;
757 1
                }
758 1
            }
759 1
        } while ($valid);
760 1
    };
761
762 1
    return new Collection($generatorFactory);
763
}
764
765
/**
766
 * Returns a lazy collection of items in $collection with $value added as first element. If $key is not provided
767
 * it will be next integer index.
768
 *
769
 * @param array|Traversable $collection
770
 * @param mixed $value
771
 * @param mixed|null $key
772
 * @return Collection
773
 */
774 View Code Duplication
function prepend($collection, $value, $key = null)
775
{
776
    $generatorFactory = function () use ($collection, $value, $key) {
777 2
        if ($key === null) {
778 1
            yield $value;
779 1
        } else {
780 1
            yield $key => $value;
781
        }
782
783 2
        foreach ($collection as $key => $value) {
784 2
            yield $key => $value;
785 2
        }
786 2
    };
787
788 2
    return new Collection($generatorFactory);
789
}
790
791
/**
792
 * Returns a lazy collection of items in $collection with $value added as last element. If $key is not provided
793
 * it will be next integer index.
794
 *
795
 * @param array|Traversable $collection
796
 * @param mixed $value
797
 * @param mixed|null $key
798
 * @return Collection
799
 */
800 View Code Duplication
function append($collection, $value, $key = null)
801
{
802
    $generatorFactory = function () use ($collection, $value, $key) {
803 8
        foreach ($collection as $k => $v) {
804 8
            yield $k => $v;
805 8
        }
806
807 8
        if ($key === null) {
808 7
            yield $value;
809 7
        } else {
810 1
            yield $key => $value;
811
        }
812 8
    };
813
814 8
    return new Collection($generatorFactory);
815
}
816
817
/**
818
 * Returns a lazy collection by removing items from $collection until first item for which $function returns false.
819
 *
820
 * @param array|Traversable $collection
821
 * @param callable $function ($value, $key)
822
 * @return Collection
823
 */
824 View Code Duplication
function dropWhile($collection, callable $function)
825
{
826
    $generatorFactory = function () use ($collection, $function) {
827 2
        $shouldDrop = true;
828 2
        foreach ($collection as $key => $value) {
829 2
            if ($shouldDrop) {
830 2
                $shouldDrop = $function($value, $key);
831 2
            }
832
833 2
            if (!$shouldDrop) {
834 2
                yield $key => $value;
835 2
            }
836 2
        }
837 2
    };
838
839 2
    return new Collection($generatorFactory);
840
}
841
842
/**
843
 * Returns a lazy collection of items from $collection until first item for which $function returns false.
844
 *
845
 * @param array|Traversable $collection
846
 * @param callable $function ($value, $key)
847
 * @return Collection
848
 */
849 View Code Duplication
function takeWhile($collection, callable $function)
850
{
851
    $generatorFactory = function () use ($collection, $function) {
852 2
        $shouldTake = true;
853 2
        foreach ($collection as $key => $value) {
854 2
            if ($shouldTake) {
855 2
                $shouldTake = $function($value, $key);
856 2
            }
857
858 2
            if ($shouldTake) {
859 2
                yield $key => $value;
860 2
            }
861 2
        }
862 2
    };
863
864 2
    return new Collection($generatorFactory);
865
}
866
867
/**
868
 * Returns a lazy collection. A result of calling map and flatten(1)
869
 *
870
 * @param array|Traversable $collection
871
 * @param callable $function ($value, $key)
872
 * @return Collection
873
 */
874
function mapcat($collection, callable $function)
875
{
876 1
    return flatten(map($collection, $function), 1);
877
}
878
879
/**
880
 * Returns a lazy collection [take($collection, $position), drop($collection, $position)]
881
 *
882
 * @param array|Traversable $collection
883
 * @param int $position
884
 * @return Collection
885
 */
886
function splitAt($collection, $position)
887
{
888
    $generatorFactory = function () use ($collection, $position) {
889 1
        yield take($collection, $position);
890 1
        yield drop($collection, $position);
891 1
    };
892
893 1
    return new Collection($generatorFactory);
894
}
895
896
/**
897
 * Returns a lazy collection [takeWhile($collection, $function), dropWhile($collection, $function)]
898
 *
899
 * @param array|Traversable $collection
900
 * @param callable $function ($value, $key)
901
 * @return Collection
902
 */
903
function splitWith($collection, callable $function)
904
{
905
    $generatorFactory = function () use ($collection, $function) {
906 1
        yield takeWhile($collection, $function);
907 1
        yield dropWhile($collection, $function);
908 1
    };
909
910 1
    return new Collection($generatorFactory);
911
}
912
913
/**
914
 * Returns a lazy collection with items from $collection but values that are found in keys of $replacementMap
915
 * are replaced by their values.
916
 *
917
 * @param array|Traversable $collection
918
 * @param array|Traversable $replacementMap
919
 * @return Collection
920
 */
921
function replace($collection, $replacementMap)
922
{
923
    $generatorFactory = function () use ($collection, $replacementMap) {
924 1
        foreach ($collection as $key => $value) {
925 1
            $newValue = getOrDefault($replacementMap, $value, $value);
926 1
            yield $key => $newValue;
927 1
        }
928 1
    };
929
930 1
    return new Collection($generatorFactory);
931
}
932
933
/**
934
 * Returns a lazy collection of reduction steps.
935
 *
936
 * @param array|Traversable $collection
937
 * @param callable $function
938
 * @param mixed $startValue
939
 * @return Collection
940
 */
941 View Code Duplication
function reductions($collection, callable $function, $startValue)
942
{
943
    $generatorFactory = function () use ($collection, $function, $startValue) {
944 1
        $tmp = duplicate($startValue);
945
946 1
        yield $tmp;
947 1
        foreach ($collection as $key => $value) {
948 1
            $tmp = $function($tmp, $value, $key);
949 1
            yield $tmp;
950 1
        }
951 1
    };
952
953 1
    return new Collection($generatorFactory);
954
}
955
956
/**
957
 * Returns a lazy collection of every nth ($step) item in  $collection.
958
 *
959
 * @param array|Traversable $collection
960
 * @param int $step
961
 * @return Collection
962
 */
963
function takeNth($collection, $step)
964
{
965
    $generatorFactory = function () use ($collection, $step) {
966 1
        $index = 0;
967 1
        foreach ($collection as $key => $value) {
968 1
            if ($index % $step == 0) {
969 1
                yield $key => $value;
970 1
            }
971
972 1
            $index++;
973 1
        }
974 1
    };
975
976 1
    return new Collection($generatorFactory);
977
}
978
979
/**
980
 * Returns a lazy collection of collections of $numberOfItems items each, at $step step
981
 * apart. If $step is not supplied, defaults to $numberOfItems, i.e. the partitions
982
 * do not overlap. If a $padding collection is supplied, use its elements as
983
 * necessary to complete last partition up to $numberOfItems items. In case there are
984
 * not enough padding elements, return a partition with less than $numberOfItems items.
985
 *
986
 * @param $collection
987
 * @param $numberOfItems
988
 * @param int $step
989
 * @param array $padding
990
 * @return Collection
991
 */
992
function partition($collection, $numberOfItems, $step = -1, $padding = [])
993
{
994
    $generatorFactory = function () use ($collection, $numberOfItems, $step, $padding) {
995 1
        $buffer = [];
996 1
        $itemsToSkip = 0;
997 1
        $tmpStep = $step ?: $numberOfItems;
998
999 1
        foreach ($collection as $key => $value) {
1000 1
            if (count($buffer) == $numberOfItems) {
1001 1
                yield dereferenceKeyValue($buffer);
1002
1003 1
                $buffer = array_slice($buffer, $tmpStep);
1004 1
                $itemsToSkip =  $tmpStep - $numberOfItems;
1005 1
            }
1006
1007 1
            if ($itemsToSkip <= 0) {
1008 1
                $buffer[] = [$key, $value];
1009 1
            } else {
1010 1
                $itemsToSkip--;
1011
            }
1012 1
        }
1013
1014 1
        yield take(
1015 1
            concat(dereferenceKeyValue($buffer), $padding),
1016
            $numberOfItems
1017 1
        );
1018 1
    };
1019
1020 1
    return new Collection($generatorFactory);
1021
}
1022
1023
/**
1024
 * Returns a lazy collection created by partitioning $collection each time $function returned a different value.
1025
 *
1026
 * @param array|Traversable $collection
1027
 * @param callable $function
1028
 * @return Collection
1029
 */
1030
function partitionBy($collection, callable $function)
1031
{
1032
    $generatorFactory = function () use ($collection, $function) {
1033 1
        $result = null;
1034 1
        $buffer = [];
1035
1036 1
        foreach ($collection as $key => $value) {
1037 1
            $newResult = $function($value, $key);
1038
1039 1
            if (!empty($buffer) && $result != $newResult) {
1040 1
                yield dereferenceKeyValue($buffer);
1041 1
                $buffer = [];
1042 1
            }
1043
1044 1
            $result = $newResult;
1045 1
            $buffer[] = [$key, $value];
1046 1
        }
1047
1048 1
        if (!empty($buffer)) {
1049 1
            yield dereferenceKeyValue($buffer);
1050 1
        }
1051 1
    };
1052
1053 1
    return new Collection($generatorFactory);
1054
}
1055
1056
/**
1057
 * Returns nth ($position) item from $collection. If $position is greater than $collection size, throws ItemNotFound.
1058
 *
1059
 * @param array|Traversable $collection
1060
 * @param int $position
1061
 * @return mixed
1062
 */
1063
function getNth($collection, $position)
1064
{
1065 13
    return get(values($collection), $position);
1066
}
1067
1068
/**
1069
 * Returns a lazy collection by picking a $key key from each sub-collection of $collection.
1070
 *
1071
 * @param array|Traversable $collection
1072
 * @param mixed $key
1073
 * @return Collection
1074
 */
1075
function pluck($collection, $key)
1076
{
1077
    $generatorFactory = function () use ($collection, $key) {
1078 1
        return map(
1079 1
            $collection,
1080
            function($value) use ($key) {
1081 1
                return $value[$key];
1082
            }
1083 1
        );
1084 1
    };
1085
1086 1
    return new Collection($generatorFactory);
1087
1088
}
1089
1090
/**
1091
 * Returns a lazy collection of $value repeated $times times. If $times is not provided the collection is infinite.
1092
 *
1093
 * @param mixed $value
1094
 * @param int $times
1095
 * @return Collection
1096
 */
1097
function repeat($value, $times = -1)
1098
{
1099
    $generatorFactory = function () use ($value, $times) {
1100 3
        $tmpTimes = $times;
1101
1102 3
        while ($tmpTimes != 0) {
1103 3
            yield $value;
1104
1105 3
            $tmpTimes = $tmpTimes < 0 ? -1 : $tmpTimes - 1;
1106 3
        }
1107 3
    };
1108
1109 3
    return new Collection($generatorFactory);
1110
}
1111
1112
/**
1113
 * Returns a lazy collection of numbers starting at $start, incremented by $step until $end is reached.
1114
 *
1115
 * @param int $start
1116
 * @param int|null $end
1117
 * @param int $step
1118
 * @return Collection
1119
 */
1120
function range($start = 0, $end = null, $step = 1)
1121
{
1122
    $generatorFactory = function () use ($start, $end, $step) {
1123 2
        return iterate(
1124 2
            $start,
1125
            function($value) use ($step, $end) {
1126 2
                $result = $value + $step;
1127
1128 2
                if ($end !== null && $result > $end) {
1129 1
                    throw new NoMoreItems;
1130
                }
1131
1132 2
                return $result;
1133
            }
1134 2
        );
1135 2
    };
1136
1137 2
    return new Collection($generatorFactory);
1138
}
1139
1140
//helpers
1141
/**
1142
 * Returns true if $input is array or Traversable object.
1143
 *
1144
 * @param mixed $input
1145
 * @return bool
1146
 */
1147
function isCollection($input)
1148
{
1149 13
    return is_array($input) || $input instanceof Traversable;
1150
}
1151
1152
/**
1153
 * Returns duplicated/cloned $input that has no relation to the original one. Used for making sure there are no side
1154
 * effect in functions.
1155
 *
1156
 * @param $input
1157
 * @return mixed
1158
 */
1159
function duplicate($input)
1160
{
1161 8
    if (is_array($input)) {
1162
        return toArray(
1163
            map(
1164
                $input,
1165
                function($i) {
1166
                    return duplicate($i);
1167
                }
1168
            )
1169
        );
1170 8
    } elseif (is_object($input)) {
1171 2
        return clone $input;
1172
    } else {
1173 8
        return $input;
1174
    }
1175
}
1176
1177
/**
1178
 * Transforms [[$key, $value], [$key2, $value2]] into [$key => $value, $key2 => $value2]. Used as a helper
1179
 *
1180
 * @param array|Traversable $collection
1181
 * @return Collection
1182
 */
1183
function dereferenceKeyValue($collection)
1184
{
1185
    $generatorFactory = function () use ($collection) {
1186 4
        foreach ($collection as $value) {
1187 4
            yield $value[0] => $value[1];
1188 4
        }
1189 4
    };
1190
1191 4
    return new Collection($generatorFactory);
1192
}
1193
1194
/**
1195
 * Realizes collection - turns lazy collection into non-lazy one by iterating over it and storing the key/values.
1196
 *
1197
 * @param array|Traversable $collection
1198
 * @return Collection
1199
 */
1200
function realize($collection)
1201
{
1202 1
    return new Collection(toArray($collection));
1203
}
1204
1205
/**
1206
 * Returns a callable that can be used to get data from an input collection
1207
 *
1208
 * @param string|callable
1209
 * @return callable
1210
 */
1211
function getCallable($function)
1212
{
1213 1
    if(is_callable($function)) {
1214
        return $function;
1215
    }
1216
1217
    return function($item, $key) use($function) {
0 ignored issues
show
The parameter $key is not used and could be removed.

This check looks from parameters that have been defined for a function or method, but which are not used in the method body.

Loading history...
1218 1
        return isset($item[$function]) ? $item[$function] : null;
1219 1
    };
1220
}
1221