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
Branch master (878646)
by Dušan
06:45
created

collection_functions.php ➔ transpose()   A

Complexity

Conditions 2
Paths 2

Size

Total Lines 21
Code Lines 12

Duplication

Lines 0
Ratio 0 %

Code Coverage

Tests 14
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 12
c 0
b 0
f 0
nc 2
nop 1
dl 0
loc 21
ccs 14
cts 14
cp 1
crap 2
rs 9.3142
1
<?php
2
3
namespace DusanKasan\Knapsack;
4
5
use DusanKasan\Knapsack\Exceptions\InvalidArgument;
6
use DusanKasan\Knapsack\Exceptions\ItemNotFound;
7
use DusanKasan\Knapsack\Exceptions\NoMoreItems;
8
use Traversable;
9
10
/**
11
 * Converts $collection to array. If there are multiple items with the same key, only the last will be preserved.
12
 *
13
 * @param array|Traversable $collection
14
 * @return array
15
 */
16
function toArray($collection)
17
{
18 66
    $arr = [];
19 66
    foreach ($collection as $key => $value) {
20 66
        $arr[$key] = $value;
21 66
    }
22
23 66
    return $arr;
24
}
25
26
/**
27
 * Returns a lazy collection of distinct items in $collection.
28
 *
29
 * @param array|Traversable $collection
30
 * @return Collection
31
 */
32
function distinct($collection)
33
{
34
    $generatorFactory = function () use ($collection) {
35 1
        $distinctValues = [];
36
37 1
        foreach ($collection as $key => $value) {
38 1
            if (!in_array($value, $distinctValues)) {
39 1
                $distinctValues[] = $value;
40 1
                yield $key => $value;
41 1
            }
42 1
        }
43 1
    };
44
45 1
    return new Collection($generatorFactory);
46
}
47
48
/**
49
 * Returns number of items in $collection.
50
 *
51
 * @param array|Traversable $collection
52
 * @return int
53
 */
54
function size($collection)
55
{
56 8
    $result = 0;
57 8
    foreach ($collection as $value) {
58 8
        $result++;
59 8
    }
60
61 8
    return $result;
62
}
63
64
/**
65
 * Returns a non-lazy collection with items from $collection in reversed order.
66
 *
67
 * @param array|Traversable $collection
68
 * @return Collection
69
 */
70
function reverse($collection)
71
{
72
    $generatorFactory = function () use ($collection) {
73 4
        $array = [];
74 4
        foreach ($collection as $key => $value) {
75 3
            $array[] = [$key, $value];
76 4
        }
77
78 5
        return map(
79 4
            indexBy(
80 4
                array_reverse($array),
81
                function ($item) {
82 3
                    return $item[0];
83
                }
84 4
            ),
85
            function ($item) {
86 3
                return $item[1];
87
            }
88 4
        );
89 4
    };
90
91 4
    return new Collection($generatorFactory);
92
}
93
94
/**
95
 * Returns a lazy collection of values from $collection (i.e. the keys are reset).
96
 *
97
 * @param array|Traversable $collection
98
 * @return Collection
99
 */
100
function values($collection)
101
{
102
    $generatorFactory = function () use ($collection) {
103 32
        foreach ($collection as $value) {
104 30
            yield $value;
105 26
        }
106 32
    };
107
108 32
    return new Collection($generatorFactory);
109
}
110
111
/**
112
 * Returns a lazy collection of keys from $collection.
113
 *
114
 * @param array|Traversable $collection
115
 * @return Collection
116
 */
117
function keys($collection)
118
{
119
    $generatorFactory = function () use ($collection) {
120 1
        foreach ($collection as $key => $value) {
121 1
            yield $key;
122 1
        }
123 1
    };
124
125 1
    return new Collection($generatorFactory);
126
}
127
128
/**
129
 * Returns a lazy collection of items from $collection repeated infinitely.
130
 *
131
 * @param array|Traversable $collection
132
 * @return Collection
133
 */
134
function cycle($collection)
135
{
136
    $generatorFactory = function () use ($collection) {
137 1
        while (true) {
138 1
            foreach ($collection as $key => $value) {
139 1
                yield $key => $value;
140 1
            }
141 1
        }
142 1
    };
143
144 1
    return new Collection($generatorFactory);
145
}
146
147
/**
148
 * Returns a non-lazy collection of shuffled items from $collection.
149
 *
150
 * @param array|Traversable $collection
151
 * @return Collection
152
 */
153
function shuffle($collection)
154
{
155 1
    $buffer = [];
156 1
    foreach ($collection as $key => $value) {
157 1
        $buffer[] = [$key, $value];
158 1
    }
159
160 1
    \shuffle($buffer);
161
162 1
    return dereferenceKeyValue($buffer);
163
}
164
165
/**
166
 * Returns true if $collection does not contain any items.
167
 *
168
 * @param array|Traversable $collection
169
 * @return bool
170
 */
171
function isEmpty($collection)
172
{
173 3
    foreach ($collection as $value) {
174 1
        return false;
175 2
    }
176
177 2
    return true;
178
}
179
180
/**
181
 * Returns true if $collection does contain any items.
182
 *
183
 * @param array|Traversable $collection
184
 * @return bool
185
 */
186
function isNotEmpty($collection)
187
{
188 2
    return !isEmpty($collection);
189
}
190
191
/**
192
 * Returns a collection where keys are distinct values from $collection and values are number of occurrences of each
193
 * value.
194
 *
195
 * @param array|Traversable $collection
196
 * @return Collection
197
 */
198
function frequencies($collection)
199
{
200 1
    return countBy($collection, '\DusanKasan\Knapsack\identity');
201
}
202
203
/**
204
 * Returns the first item of $collection or throws ItemNotFound if #collection is empty.
205
 *
206
 * @param array|Traversable $collection
207
 * @return mixed
208
 */
209
function first($collection)
210
{
211 13
    return get(values($collection), 0);
212
}
213
214
/**
215
 * Returns the last item of $collection or throws ItemNotFound if #collection is empty.
216
 *
217
 * @param array|Traversable $collection
218
 * @return mixed
219
 */
220
function last($collection)
221
{
222 2
    return first(reverse($collection));
223
}
224
225
/**
226
 * Returns a lazy collection of items of $collection where value of each item is set to the return value of calling
227
 * $function on its value and key.
228
 *
229
 * @param array|Traversable $collection
230
 * @param callable $function ($value, $key)
231
 * @return Collection
232
 */
233 View Code Duplication
function map($collection, callable $function)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
234
{
235
    $generatorFactory = function () use ($collection, $function) {
236 17
        foreach ($collection as $key => $value) {
237 16
            yield $key => $function($value, $key);
238 16
        }
239 17
    };
240
241 17
    return new Collection($generatorFactory);
242
}
243
244
/**
245
 * Returns a lazy collection of items from $collection for which $function returns true.
246
 *
247
 * @param array|Traversable $collection
248
 * @param callable|null $function ($value, $key)
249
 * @return Collection
250
 */
251
function filter($collection, callable $function = null)
252
{
253 7
    if (null === $function) {
254
        $function = function ($value) {
255 1
            return (bool) $value;
256 1
        };
257 1
    }
258
    ;
259
260
    $generatorFactory = function () use ($collection, $function) {
261 7
        foreach ($collection as $key => $value) {
262 7
            if ($function($value, $key)) {
263 5
                yield $key => $value;
264 5
            }
265 7
        }
266 7
    };
267
268 7
    return new Collection($generatorFactory);
269
}
270
271
/**
272
 * Returns a lazy collection with items from all $collections passed as argument appended together
273
 *
274
 * @param array|Traversable ...$collections
275
 * @return Collection
276
 */
277
function concat(...$collections)
278
{
279
    $generatorFactory = function () use ($collections) {
280 5
        foreach ($collections as $collection) {
281 5
            foreach ($collection as $key => $value) {
282 5
                yield $key => $value;
283 5
            }
284 5
        }
285 5
    };
286
287 5
    return new Collection($generatorFactory);
288
}
289
290
/**
291
 * Reduces the collection to single value by iterating over the collection and calling $reduction while
292
 * passing $startValue and current key/item as parameters. The output of $function is used as $startValue in
293
 * next iteration. The output of $function on last element is the return value of this function.
294
 *
295
 * @param array|Traversable $collection
296
 * @param callable $function ($value, $key)
297
 * @param mixed $startValue
298
 * @return mixed
299
 */
300
function reduce($collection, callable $function, $startValue)
301
{
302 3
    $tmp = duplicate($startValue);
303
304 3
    foreach ($collection as $key => $value) {
305 3
        $tmp = $function($tmp, $value, $key);
306 3
    }
307
308 3
    return $tmp;
309
}
310
311
/**
312
 * Flattens multiple levels of nesting in collection. If $levelsToFlatten is not specified, flattens all levels of
313
 * nesting.
314
 *
315
 * @param array|Traversable $collection
316
 * @param int $levelsToFlatten -1 to flatten everything
317
 * @return Collection
318
 */
319
function flatten($collection, $levelsToFlatten = -1)
320
{
321
    $generatorFactory = function () use ($collection, $levelsToFlatten) {
322 3
        $flattenNextLevel = $levelsToFlatten < 0 || $levelsToFlatten > 0;
323 3
        $childLevelsToFlatten = $levelsToFlatten > 0 ? $levelsToFlatten - 1 : $levelsToFlatten;
324
325 3
        foreach ($collection as $key => $value) {
326 3
            if ($flattenNextLevel && (is_array($value) || $value instanceof Traversable)) {
327 3
                foreach (flatten($value, $childLevelsToFlatten) as $childKey => $childValue) {
328 3
                    yield $childKey => $childValue;
329 3
                }
330 3
            } else {
331 3
                yield $key => $value;
332
            }
333 3
        }
334 3
    };
335
336 3
    return new Collection($generatorFactory);
337
}
338
339
/**
340
 * Returns a non-lazy collection sorted using $collection($item1, $item2, $key1, $key2 ). $collection should
341
 * return true if first item is larger than the second and false otherwise.
342
 *
343
 * @param array|Traversable $collection
344
 * @param callable $function ($value1, $value2, $key1, $key2)
345
 * @return Collection
346
 */
347
function sort($collection, callable $function)
348
{
349 2
    $array = iterator_to_array(
350 2
        values(
351 2
            map(
352 2
                $collection,
353
                function ($value, $key) {
354 2
                    return [$key, $value];
355
                }
356 2
            )
357 2
        )
358 2
    );
359
360 2
    uasort(
361 2
        $array,
362
        function ($a, $b) use ($function) {
363 2
            return $function($a[1], $b[1], $a[0], $b[0]);
364
        }
365 2
    );
366
367 2
    return dereferenceKeyValue($array);
368
}
369
370
/**
371
 * Returns a lazy collection that is a part of $collection starting from $from position and ending in $to position.
372
 * If $to is not provided, the returned collection is contains all items from $from until end of $collection. All items
373
 * before $from are iterated over, but not included in result.
374
 *
375
 * @param array|Traversable $collection
376
 * @param int $from
377
 * @param int $to -1 to slice until end
378
 * @return Collection
379
 */
380
function slice($collection, $from, $to = -1)
381
{
382
    $generatorFactory = function () use ($collection, $from, $to) {
383 15
        $index = 0;
384 15
        foreach ($collection as $key => $value) {
385 15
            if ($index >= $from && ($index < $to || $to == -1)) {
386 15
                yield $key => $value;
387 15
            } elseif ($index >= $to && $to >= 0) {
388 12
                break;
389
            }
390
391 15
            $index++;
392 15
        }
393 15
    };
394
395 15
    return new Collection($generatorFactory);
396
}
397
398
/**
399
 * Returns a non-lazy collection of items grouped by the result of $function.
400
 *
401
 * @param array|Traversable $collection
402
 * @param callable $function ($value, $key)
403
 * @return Collection
404
 */
405
function groupBy($collection, callable $function)
406
{
407 4
    $result = [];
408
409 4
    foreach ($collection as $key => $value) {
410 4
        $newKey = $function($value, $key);
411
412 4
        $group = isset($result[$newKey]) ? $result[$newKey] : new Collection([]);
413 4
        $result[$newKey] = $group->append($value);
414 4
    }
415
416 4
    return Collection::from($result);
417
}
418
419
/**
420
 * Returns a non-lazy collection of items grouped by the value at given key. Ignores non-collection items and items
421
 * without the given keys
422
 *
423
 * @param array|Traversable $collection
424
 * @param mixed $key
425
 * @return Collection
426
 */
427
function groupByKey($collection, $key)
428
{
429
    $generatorFactory = function () use ($collection, $key) {
430
431 1
        return groupBy(
432 1
            filter(
433 1
                $collection,
434
                function ($item) use ($key) {
435 1
                    return isCollection($item) && has($item, $key);
436
                }
437 1
            ),
438
            function ($value) use ($key) {
439 1
                return get($value, $key);
440
            }
441 1
        );
442 1
    };
443
444 1
    return new Collection($generatorFactory);
445
}
446
/**
447
 * Executes $function for each item in $collection
448
 *
449
 * @param array|Traversable $collection
450
 * @param callable $function ($value, $key)
451
 * @return Collection
452
 */
453 View Code Duplication
function each($collection, callable $function)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
454
{
455
    $generatorFactory = function () use ($collection, $function) {
456 1
        foreach ($collection as $key => $value) {
457 1
            $function($value, $key);
458
459 1
            yield $key => $value;
460 1
        }
461 1
    };
462
463 1
    return new Collection($generatorFactory);
464
}
465
466
/**
467
 * Returns an item with $key key from $collection. If that key is not present, throws ItemNotFound.
468
 *
469
 * @param array|Traversable $collection
470
 * @param mixed $key
471
 * @return mixed
472
 */
473
function get($collection, $key)
474
{
475 20
    foreach ($collection as $valueKey => $value) {
476 18
        if ($key === $valueKey) {
477 17
            return $value;
478
        }
479 16
    }
480
481 9
    throw new ItemNotFound;
482
}
483
484
/**
485
 * Returns an item with $key key from $collection. If that key is not present, returns $default.
486
 *
487
 * @param array|Traversable $collection
488
 * @param mixed $key
489
 * @param mixed $default value returned if key is not found
490
 * @return mixed
491
 */
492
function getOrDefault($collection, $key, $default)
493
{
494
    try {
495 3
        return get($collection, $key);
496 3
    } catch (ItemNotFound $e) {
497 3
        return $default;
498
    }
499
}
500
501
/**
502
 * Returns the first item from $collection for which $function returns true. If item like that is not present, returns
503
 * $default.
504
 *
505
 * @param array|Traversable $collection
506
 * @param callable $function ($value, $key)
507
 * @param mixed $default
508
 * @return mixed
509
 */
510
function find($collection, callable $function, $default = null)
511
{
512 1
    foreach ($collection as $key => $value) {
513 1
        if ($function($value, $key)) {
514 1
            return $value;
515
        }
516 1
    }
517
518 1
    return $default;
519
}
520
521
/**
522
 * Returns a lazy collection by changing keys of $collection for each item to the result of $function for
523
 * that item.
524
 *
525
 * @param array|Traversable $collection
526
 * @param callable $function ($value, $key)
527
 * @return Collection
528
 */
529 View Code Duplication
function indexBy($collection, callable $function)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
530
{
531
    $generatorFactory = function () use ($collection, $function) {
532 5
        foreach ($collection as $key => $value) {
533 4
            yield $function($value, $key) => $value;
534 4
        }
535 5
    };
536
537 5
    return new Collection($generatorFactory);
538
}
539
540
/**
541
 * Returns a non-lazy collection of items whose keys are the return values of $function and values are the number of
542
 * items in this collection for which the $function returned this value.
543
 *
544
 * @param array|Traversable $collection
545
 * @param callable $function ($value, $key)
546
 * @return Collection
547
 */
548
function countBy($collection, callable $function)
549
{
550 2
    return map(
551 2
        groupBy($collection, $function),
552
        '\DusanKasan\Knapsack\size'
553 2
    );
554
}
555
556
/**
557
 * Returns true if $function returns true for every item in $collection
558
 *
559
 * @param array|Traversable $collection
560
 * @param callable $function ($value, $key)
561
 * @return bool
562
 */
563
function every($collection, callable $function)
564
{
565 1
    foreach ($collection as $key => $value) {
566 1
        if (!$function($value, $key)) {
567 1
            return false;
568
        }
569 1
    }
570
571 1
    return true;
572
}
573
574
/**
575
 * Returns true if $function returns true for at least one item in $collection.
576
 *
577
 * @param array|Traversable $collection
578
 * @param callable $function ($value, $key)
579
 * @return bool
580
 */
581
function some($collection, callable $function)
582
{
583 4
    foreach ($collection as $key => $value) {
584 4
        if ($function($value, $key)) {
585 2
            return true;
586
        }
587 3
    }
588
589 3
    return false;
590
}
591
592
/**
593
 * Returns true if $needle is found in $collection values.
594
 *
595
 * @param $collection
596
 * @param mixed $needle
597
 * @return bool
598
 */
599
function contains($collection, $needle)
600
{
601 1
    foreach ($collection as $key => $value) {
602 1
        if ($value === $needle) {
603 1
            return true;
604
        }
605 1
    }
606
607 1
    return false;
608
}
609
610
/**
611
 * Reduce that walks from right to the left.
612
 *
613
 * @param array|Traversable $collection
614
 * @param callable $function
615
 * @param mixed $startValue
616
 * @return mixed
617
 */
618
function reduceRight($collection, callable $function, $startValue)
619
{
620 1
    return reduce(reverse($collection), $function, $startValue);
621
}
622
623
/**
624
 * Returns a lazy collection of first $numberOfItems items of $collection.
625
 *
626
 * @param array|Traversable $collection
627
 * @param int $numberOfItems
628
 * @return Collection
629
 */
630
function take($collection, $numberOfItems)
631
{
632 12
    return slice($collection, 0, $numberOfItems);
633
}
634
635
/**
636
 * Returns a lazy collection of all but first $numberOfItems items of $collection.
637
 *
638
 * @param array|Traversable $collection
639
 * @param int $numberOfItems
640
 * @return Collection
641
 */
642
function drop($collection, $numberOfItems)
643
{
644 4
    return slice($collection, $numberOfItems);
645
}
646
647
/**
648
 * Returns a lazy collection of values, where first value is $value and all subsequent values are computed by applying
649
 * $function to the last value in the collection. By default this produces an infinite collection. However you can
650
 * end the collection by throwing a NoMoreItems exception.
651
 *
652
 * @param mixed $value
653
 * @param callable $function ($value, $key)
654
 * @return Collection
655
 */
656
function iterate($value, callable $function)
657
{
658 4
    $duplicated = duplicate($value);
659
    $generatorFactory = function () use ($duplicated, $function) {
660 4
        $value = $duplicated;
661
662 4
        yield $value;
663
664 4
        while (true) {
665
            try {
666 4
                $value = $function($value);
667 4
                yield $value;
668 4
            } catch (NoMoreItems $e) {
669 2
                break;
670
            }
671 4
        }
672 4
    };
673
674 4
    return new Collection($generatorFactory);
675
}
676
677
/**
678
 * Returns a lazy collection of items from $collection for which $function returned true.
679
 *
680
 * @param array|Traversable $collection
681
 * @param callable $function ($value, $key)
682
 * @return Collection
683
 */
684
function reject($collection, callable $function)
685
{
686 2
    return filter(
687 2
        $collection,
688
        function ($value, $key) use ($function) {
689 2
            return !$function($value, $key);
690
        }
691 2
    );
692
}
693
694
/**
695
 * Returns a lazy collection of items in $collection without the last $numberOfItems items.
696
 *
697
 * @param array|Traversable $collection
698
 * @param int $numberOfItems
699
 * @return Collection
700
 */
701
function dropLast($collection, $numberOfItems = 1)
702
{
703
    $generatorFactory = function () use ($collection, $numberOfItems) {
704 1
        $buffer = [];
705
706 1
        foreach ($collection as $key => $value) {
707 1
            $buffer[] = [$key, $value];
708
709 1
            if (count($buffer) > $numberOfItems) {
710 1
                $val = array_shift($buffer);
711 1
                yield $val[0] => $val[1];
712 1
            }
713 1
        }
714 1
    };
715
716 1
    return new Collection($generatorFactory);
717
}
718
719
/**
720
 * Returns a lazy collection of items from $collection separated by $separator.
721
 *
722
 * @param array|Traversable $collection
723
 * @param mixed $separator
724
 * @return Collection
725
 */
726
function interpose($collection, $separator)
727
{
728
    $generatorFactory = function () use ($collection, $separator) {
729 1
        foreach (take($collection, 1) as $key => $value) {
730 1
            yield $key => $value;
731 1
        }
732
733 1
        foreach (drop($collection, 1) as $key => $value) {
734 1
            yield $separator;
735 1
            yield $key => $value;
736 1
        }
737 1
    };
738
739 1
    return new Collection($generatorFactory);
740
}
741
742
/**
743
 * Returns a lazy collection of first item from first collection, first item from second, second from first and
744
 * so on. Accepts any number of collections.
745
 *
746
 * @param array|Traversable ...$collections
747
 * @return Collection
748
 */
749
function interleave(...$collections)
750
{
751
    $generatorFactory = function () use ($collections) {
752 1
        $normalizedCollection = array_map(
753
            function ($collection) {
754 1
                $traversable = new Collection($collection);
755 1
                $traversable->rewind();
756 1
                return $traversable;
757 1
            },
758
            $collections
759 1
        );
760
761
        do {
762 1
            $valid = false;
763 1
            foreach ($normalizedCollection as $collection) {
764 1
                if ($collection->valid()) {
765 1
                    yield $collection->key() => $collection->current();
766 1
                    $collection->next();
767 1
                    $valid = true;
768 1
                }
769 1
            }
770 1
        } while ($valid);
771 1
    };
772
773 1
    return new Collection($generatorFactory);
774
}
775
776
/**
777
 * Returns a lazy collection of items in $collection with $value added as first element. If $key is not provided
778
 * it will be next integer index.
779
 *
780
 * @param array|Traversable $collection
781
 * @param mixed $value
782
 * @param mixed|null $key
783
 * @return Collection
784
 */
785 View Code Duplication
function prepend($collection, $value, $key = null)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
786
{
787
    $generatorFactory = function () use ($collection, $value, $key) {
788 2
        if ($key === null) {
789 1
            yield $value;
790 1
        } else {
791 1
            yield $key => $value;
792
        }
793
794 2
        foreach ($collection as $key => $value) {
795 2
            yield $key => $value;
796 2
        }
797 2
    };
798
799 2
    return new Collection($generatorFactory);
800
}
801
802
/**
803
 * Returns a lazy collection of items in $collection with $value added as last element. If $key is not provided
804
 * it will be next integer index.
805
 *
806
 * @param array|Traversable $collection
807
 * @param mixed $value
808
 * @param mixed|null $key
809
 * @return Collection
810
 */
811 View Code Duplication
function append($collection, $value, $key = null)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
812
{
813
    $generatorFactory = function () use ($collection, $value, $key) {
814 11
        foreach ($collection as $k => $v) {
815 11
            yield $k => $v;
816 11
        }
817
818 11
        if ($key === null) {
819 9
            yield $value;
820 9
        } else {
821 2
            yield $key => $value;
822
        }
823 11
    };
824
825 11
    return new Collection($generatorFactory);
826
}
827
828
/**
829
 * Returns a lazy collection by removing items from $collection until first item for which $function returns false.
830
 *
831
 * @param array|Traversable $collection
832
 * @param callable $function ($value, $key)
833
 * @return Collection
834
 */
835 View Code Duplication
function dropWhile($collection, callable $function)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
836
{
837
    $generatorFactory = function () use ($collection, $function) {
838 2
        $shouldDrop = true;
839 2
        foreach ($collection as $key => $value) {
840 2
            if ($shouldDrop) {
841 2
                $shouldDrop = $function($value, $key);
842 2
            }
843
844 2
            if (!$shouldDrop) {
845 2
                yield $key => $value;
846 2
            }
847 2
        }
848 2
    };
849
850 2
    return new Collection($generatorFactory);
851
}
852
853
/**
854
 * Returns a lazy collection of items from $collection until first item for which $function returns false.
855
 *
856
 * @param array|Traversable $collection
857
 * @param callable $function ($value, $key)
858
 * @return Collection
859
 */
860 View Code Duplication
function takeWhile($collection, callable $function)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
861
{
862
    $generatorFactory = function () use ($collection, $function) {
863 2
        $shouldTake = true;
864 2
        foreach ($collection as $key => $value) {
865 2
            if ($shouldTake) {
866 2
                $shouldTake = $function($value, $key);
867 2
            }
868
869 2
            if ($shouldTake) {
870 2
                yield $key => $value;
871 2
            }
872 2
        }
873 2
    };
874
875 2
    return new Collection($generatorFactory);
876
}
877
878
/**
879
 * Returns a lazy collection. A result of calling map and flatten(1)
880
 *
881
 * @param array|Traversable $collection
882
 * @param callable $function ($value, $key)
883
 * @return Collection
884
 */
885
function mapcat($collection, callable $function)
886
{
887 1
    return flatten(map($collection, $function), 1);
888
}
889
890
/**
891
 * Returns a lazy collection [take($collection, $position), drop($collection, $position)]
892
 *
893
 * @param array|Traversable $collection
894
 * @param int $position
895
 * @return Collection
896
 */
897
function splitAt($collection, $position)
898
{
899
    $generatorFactory = function () use ($collection, $position) {
900 1
        yield take($collection, $position);
901 1
        yield drop($collection, $position);
902 1
    };
903
904 1
    return new Collection($generatorFactory);
905
}
906
907
/**
908
 * Returns a lazy collection [takeWhile($collection, $function), dropWhile($collection, $function)]
909
 *
910
 * @param array|Traversable $collection
911
 * @param callable $function ($value, $key)
912
 * @return Collection
913
 */
914
function splitWith($collection, callable $function)
915
{
916
    $generatorFactory = function () use ($collection, $function) {
917 1
        yield takeWhile($collection, $function);
918 1
        yield dropWhile($collection, $function);
919 1
    };
920
921 1
    return new Collection($generatorFactory);
922
}
923
924
/**
925
 * Returns a lazy collection with items from $collection but values that are found in keys of $replacementMap
926
 * are replaced by their values.
927
 *
928
 * @param array|Traversable $collection
929
 * @param array|Traversable $replacementMap
930
 * @return Collection
931
 */
932 View Code Duplication
function replace($collection, $replacementMap)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
933
{
934
    $generatorFactory = function () use ($collection, $replacementMap) {
935 1
        foreach ($collection as $key => $value) {
936 1
            $newValue = getOrDefault($replacementMap, $value, $value);
937 1
            yield $key => $newValue;
938 1
        }
939 1
    };
940
941 1
    return new Collection($generatorFactory);
942
}
943
944
/**
945
 * Returns a lazy collection of reduction steps.
946
 *
947
 * @param array|Traversable $collection
948
 * @param callable $function
949
 * @param mixed $startValue
950
 * @return Collection
951
 */
952 View Code Duplication
function reductions($collection, callable $function, $startValue)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
953
{
954
    $generatorFactory = function () use ($collection, $function, $startValue) {
955 1
        $tmp = duplicate($startValue);
956
957 1
        yield $tmp;
958 1
        foreach ($collection as $key => $value) {
959 1
            $tmp = $function($tmp, $value, $key);
960 1
            yield $tmp;
961 1
        }
962 1
    };
963
964 1
    return new Collection($generatorFactory);
965
}
966
967
/**
968
 * Returns a lazy collection of every nth ($step) item in  $collection.
969
 *
970
 * @param array|Traversable $collection
971
 * @param int $step
972
 * @return Collection
973
 */
974
function takeNth($collection, $step)
975
{
976
    $generatorFactory = function () use ($collection, $step) {
977 1
        $index = 0;
978 1
        foreach ($collection as $key => $value) {
979 1
            if ($index % $step == 0) {
980 1
                yield $key => $value;
981 1
            }
982
983 1
            $index++;
984 1
        }
985 1
    };
986
987 1
    return new Collection($generatorFactory);
988
}
989
990
/**
991
 * Returns a lazy collection of collections of $numberOfItems items each, at $step step
992
 * apart. If $step is not supplied, defaults to $numberOfItems, i.e. the partitions
993
 * do not overlap. If a $padding collection is supplied, use its elements as
994
 * necessary to complete last partition up to $numberOfItems items. In case there are
995
 * not enough padding elements, return a partition with less than $numberOfItems items.
996
 *
997
 * @param array|Traversable $collection
998
 * @param $numberOfItems
999
 * @param int $step
1000
 * @param array|Traversable $padding
1001
 * @return Collection
1002
 */
1003
function partition($collection, $numberOfItems, $step = -1, $padding = [])
1004
{
1005
    $generatorFactory = function () use ($collection, $numberOfItems, $step, $padding) {
1006 1
        $buffer = [];
1007 1
        $itemsToSkip = 0;
1008 1
        $tmpStep = $step ?: $numberOfItems;
1009
1010 1
        foreach ($collection as $key => $value) {
1011 1
            if (count($buffer) == $numberOfItems) {
1012 1
                yield dereferenceKeyValue($buffer);
1013
1014 1
                $buffer = array_slice($buffer, $tmpStep);
1015 1
                $itemsToSkip = $tmpStep - $numberOfItems;
1016 1
            }
1017
1018 1
            if ($itemsToSkip <= 0) {
1019 1
                $buffer[] = [$key, $value];
1020 1
            } else {
1021 1
                $itemsToSkip--;
1022
            }
1023 1
        }
1024
1025 1
        yield take(
1026 1
            concat(dereferenceKeyValue($buffer), $padding),
1027
            $numberOfItems
1028 1
        );
1029 1
    };
1030
1031 1
    return new Collection($generatorFactory);
1032
}
1033
1034
/**
1035
 * Returns a lazy collection created by partitioning $collection each time $function returned a different value.
1036
 *
1037
 * @param array|Traversable $collection
1038
 * @param callable $function
1039
 * @return Collection
1040
 */
1041
function partitionBy($collection, callable $function)
1042
{
1043
    $generatorFactory = function () use ($collection, $function) {
1044 1
        $result = null;
1045 1
        $buffer = [];
1046
1047 1
        foreach ($collection as $key => $value) {
1048 1
            $newResult = $function($value, $key);
1049
1050 1
            if (!empty($buffer) && $result != $newResult) {
1051 1
                yield dereferenceKeyValue($buffer);
1052 1
                $buffer = [];
1053 1
            }
1054
1055 1
            $result = $newResult;
1056 1
            $buffer[] = [$key, $value];
1057 1
        }
1058
1059 1
        if (!empty($buffer)) {
1060 1
            yield dereferenceKeyValue($buffer);
1061 1
        }
1062 1
    };
1063
1064 1
    return new Collection($generatorFactory);
1065
}
1066
1067
/**
1068
 * Returns a lazy collection of $value repeated $times times. If $times is not provided the collection is infinite.
1069
 *
1070
 * @param mixed $value
1071
 * @param int $times
1072
 * @return Collection
1073
 */
1074
function repeat($value, $times = -1)
1075
{
1076
    $generatorFactory = function () use ($value, $times) {
1077 3
        $tmpTimes = $times;
1078
1079 3
        while ($tmpTimes != 0) {
1080 3
            yield $value;
1081
1082 3
            $tmpTimes = $tmpTimes < 0 ? -1 : $tmpTimes - 1;
1083 3
        }
1084 3
    };
1085
1086 3
    return new Collection($generatorFactory);
1087
}
1088
1089
/**
1090
 * Returns a lazy collection of numbers starting at $start, incremented by $step until $end is reached.
1091
 *
1092
 * @param int $start
1093
 * @param int|null $end
1094
 * @param int $step
1095
 * @return Collection
1096
 */
1097
function range($start = 0, $end = null, $step = 1)
1098
{
1099
    $generatorFactory = function () use ($start, $end, $step) {
1100 2
        return iterate(
1101 2
            $start,
1102
            function ($value) use ($step, $end) {
1103 2
                $result = $value + $step;
1104
1105 2
                if ($end !== null && $result > $end) {
1106 1
                    throw new NoMoreItems;
1107
                }
1108
1109 2
                return $result;
1110
            }
1111 2
        );
1112 2
    };
1113
1114 2
    return new Collection($generatorFactory);
1115
}
1116
1117
/**
1118
 * Returns true if $input is array or Traversable object.
1119
 *
1120
 * @param mixed $input
1121
 * @return bool
1122
 */
1123
function isCollection($input)
1124
{
1125 18
    return is_array($input) || $input instanceof Traversable;
1126
}
1127
1128
/**
1129
 * Returns duplicated/cloned $input that has no relation to the original one. Used for making sure there are no side
1130
 * effect in functions.
1131
 *
1132
 * @param $input
1133
 * @return mixed
1134
 */
1135
function duplicate($input)
1136
{
1137 8
    if (is_array($input)) {
1138 1
        return toArray(
1139 1
            map(
1140 1
                $input,
1141
                function ($i) {
1142 1
                    return duplicate($i);
1143
                }
1144 1
            )
1145 1
        );
1146 8
    } elseif (is_object($input)) {
1147 2
        return clone $input;
1148
    } else {
1149 8
        return $input;
1150
    }
1151
}
1152
1153
/**
1154
 * Transforms [[$key, $value], [$key2, $value2]] into [$key => $value, $key2 => $value2]. Used as a helper
1155
 *
1156
 * @param array|Traversable $collection
1157
 * @return Collection
1158
 */
1159
function dereferenceKeyValue($collection)
1160
{
1161
    $generatorFactory = function () use ($collection) {
1162 6
        foreach ($collection as $value) {
1163 6
            yield $value[0] => $value[1];
1164 6
        }
1165 7
    };
1166
1167 7
    return new Collection($generatorFactory);
1168
}
1169
1170
/**
1171
 * Realizes collection - turns lazy collection into non-lazy one by iterating over it and storing the key/values.
1172
 *
1173
 * @param array|Traversable $collection
1174
 * @return Collection
1175
 */
1176
function realize($collection)
1177
{
1178 1
    return dereferenceKeyValue(
1179 1
        toArray(
1180 1
            map(
1181 1
                $collection,
1182
                function ($value, $key) {
1183 1
                    return [$key, $value];
1184
                }
1185 1
            )
1186 1
        )
1187 1
    );
1188
}
1189
1190
/**
1191
 * Returns the second item of $collection or throws ItemNotFound if $collection is empty or has 1 item.
1192
 *
1193
 * @param array|Traversable $collection
1194
 * @return mixed
1195
 */
1196
function second($collection)
1197
{
1198 6
    return get(values($collection), 1);
1199
}
1200
1201
/**
1202
 * Combines $keys and $values into a lazy collection. The resulting collection has length equal to the size of smaller
1203
 * argument.
1204
 *
1205
 * @param array|Traversable $keys
1206
 * @param array|Traversable $values
1207
 * @return Collection
1208
 */
1209
function combine($keys, $values)
1210
{
1211
    $generatorFactory = function () use ($keys, $values) {
1212 1
        $keyCollection = new Collection($keys);
1213 1
        $valueCollection = new Collection($values);
1214 1
        $valueCollection->rewind();
1215
1216 1
        foreach ($keyCollection as $key) {
1217 1
            if (!$valueCollection->valid()) {
1218 1
                break;
1219
            }
1220
1221 1
            yield $key => $valueCollection->current();
1222 1
            $valueCollection->next();
1223 1
        }
1224 1
    };
1225
1226 1
    return new Collection($generatorFactory);
1227
}
1228
1229
/**
1230
 * Returns a lazy collection without the items associated to any of the keys from $keys.
1231
 *
1232
 * @param array|Traversable $collection
1233
 * @param array|Traversable $keys
1234
 * @return Collection
1235
 */
1236
function except($collection, $keys)
1237
{
1238 1
    $keys = toArray(values($keys));
1239
1240 1
    return reject(
1241 1
        $collection,
1242
        function ($value, $key) use ($keys) {
1243 1
            return in_array($key, $keys);
1244
        }
1245 1
    );
1246
}
1247
1248
/**
1249
 * Returns a lazy collection of items associated to any of the keys from $keys.
1250
 *
1251
 * @param array|Traversable $collection
1252
 * @param array|Traversable $keys
1253
 * @return Collection
1254
 */
1255
function only($collection, $keys)
1256
{
1257 2
    $keys = toArray(values($keys));
1258
1259 2
    return filter(
1260 2
        $collection,
1261
        function ($value, $key) use ($keys) {
1262 2
            return in_array($key, $keys, true);
1263
        }
1264 2
    );
1265
}
1266
1267
/**
1268
 * Returns a lazy collection of items that are in $collection but are not in any of the other arguments. Note that the
1269
 * ...$collections are iterated non-lazily.
1270
 *
1271
 * @param array|Traversable $collection
1272
 * @param array|Traversable ...$collections
1273
 * @return Collection
1274
 */
1275 View Code Duplication
function diff($collection, ...$collections)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1276
{
1277 1
    $valuesToCompare = toArray(values(concat(...$collections)));
1278
    $generatorFactory = function () use ($collection, $valuesToCompare) {
1279 1
        foreach ($collection as $key => $value) {
1280 1
            if (!in_array($value, $valuesToCompare)) {
1281 1
                yield $key => $value;
1282 1
            }
1283 1
        }
1284 1
    };
1285
1286 1
    return new Collection($generatorFactory);
1287
}
1288
1289
/**
1290
 * Returns a lazy collection of items that are in $collection and all the other arguments, indexed by the keys from the
1291
 * first collection. Note that the ...$collections are iterated non-lazily.
1292
 *
1293
 * @param array|Traversable $collection
1294
 * @param array|Traversable ...$collections
1295
 * @return Collection
1296
 */
1297 View Code Duplication
function intersect($collection, ...$collections)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1298
{
1299 1
    $valuesToCompare = toArray(values(concat(...$collections)));
1300
    $generatorFactory = function () use ($collection, $valuesToCompare) {
1301 1
        foreach ($collection as $key => $value) {
1302 1
            if (in_array($value, $valuesToCompare)) {
1303 1
                yield $key => $value;
1304 1
            }
1305 1
        }
1306 1
    };
1307
1308 1
    return new Collection($generatorFactory);
1309
}
1310
1311
/**
1312
 * Returns a lazy collection where keys and values are flipped.
1313
 *
1314
 * @param array|Traversable $collection
1315
 * @return Collection
1316
 */
1317
function flip($collection)
1318
{
1319
    $generatorFactory = function () use ($collection) {
1320 1
        foreach ($collection as $key => $value) {
1321 1
            yield $value => $key;
1322 1
        }
1323 1
    };
1324
1325 1
    return new Collection($generatorFactory);
1326
}
1327
1328
/**
1329
 * Checks for the existence of an item with key $key in $collection.
1330
 *
1331
 * @param array|Traversable $collection
1332
 * @param mixed $key
1333
 * @return bool
1334
 */
1335
function has($collection, $key)
1336
{
1337
    try {
1338 2
        get($collection, $key);
1339 2
        return true;
1340 2
    } catch (ItemNotFound $e) {
1341 2
        return false;
1342
    }
1343
}
1344
1345
/**
1346
 * Returns a lazy collection of non-lazy collections of items from nth position from each passed collection. Stops when
1347
 * any of the collections don't have an item at the nth position.
1348
 *
1349
 * @param array|Traversable[] ...$collections
1350
 * @return Collection
1351
 */
1352
function zip(...$collections)
1353
{
1354 1
    $normalizedCollections = [];
1355 1
    foreach ($collections as $collection) {
1356 1
        $traversable = new Collection($collection);
1357 1
        $traversable->rewind();
1358 1
        $normalizedCollections[] = $traversable;
1359 1
    }
1360
1361
    $generatorFactory = function () use ($normalizedCollections) {
1362 1
        while (true) {
1363 1
            $isMissingItems = false;
1364 1
            $zippedItem = new Collection([]);
1365
1366 1
            foreach ($normalizedCollections as $collection) {
1367 1
                if (!$collection->valid()) {
1368 1
                    $isMissingItems = true;
1369 1
                    break;
1370
                }
1371
1372 1
                $zippedItem = append($zippedItem, $collection->current(), $collection->key());
1373 1
                $collection->next();
1374 1
            }
1375
1376 1
            if (!$isMissingItems) {
1377 1
                yield $zippedItem;
1378 1
            } else {
1379 1
                break;
1380
            }
1381 1
        }
1382 1
    };
1383
1384 1
    return new Collection($generatorFactory);
1385
}
1386
1387
/**
1388
 * Transpose each item in a collection, interchanging the row and column indexes.
1389
 * Can only transpose collections of collections. Otherwise an InvalidArgument is raised.
1390
 *
1391
 * @param Collection $collection
1392
 * @return Collection
1393
 */
1394
function transpose($collection)
1395
{
1396
    if (some($collection, function ($value) {
1397 3
        return !($value instanceof Collection);
1398 3
    })) {
1399 1
        throw new InvalidArgument('Can only transpose collections of collections.');
1400
    }
1401 2
    return Collection::from(
1402 2
        array_map(
1403
            function (...$items) {
1404 2
                return new Collection($items);
1405 2
            },
1406 2
            ...toArray(
1407 2
                map(
1408 2
                    $collection,
1409
                    'DusanKasan\Knapsack\toArray'
1410 2
                )
1411 2
            )
1412 2
        )
1413 2
    );
1414
}
1415
1416
/**
1417
 * Returns a lazy collection of data extracted from $collection items by dot separated key path. Supports the *
1418
 * wildcard. If a key contains \ or * it must be escaped using \ character.
1419
 *
1420
 * @param array|Traversable $collection
1421
 * @param mixed $keyPath
1422
 * @return Collection
1423
 */
1424
function extract($collection, $keyPath)
1425
{
1426 1
    preg_match_all('/(.*[^\\\])(?:\.|$)/U', $keyPath, $matches);
1427 1
    $pathParts = $matches[1];
1428
1429
    $extractor = function ($coll) use ($pathParts) {
1430 1
        foreach ($pathParts as $pathPart) {
1431 1
            $coll = flatten(filter($coll, '\DusanKasan\Knapsack\isCollection'), 1);
1432
1433 1
            if ($pathPart != '*') {
1434 1
                $pathPart = str_replace(['\.', '\*'], ['.', '*'], $pathPart);
1435 1
                $coll = values(only($coll, [$pathPart]));
1436 1
            }
1437 1
        }
1438
1439 1
        return $coll;
1440 1
    };
1441
1442
    $generatorFactory = function () use ($collection, $extractor) {
1443 1
        foreach ($collection as $item) {
1444 1
            foreach ($extractor([$item]) as $extracted) {
1445 1
                yield $extracted;
1446 1
            }
1447 1
        }
1448 1
    };
1449
1450 1
    return new Collection($generatorFactory);
1451
}
1452
1453
/**
1454
 * Checks whether $collection has exactly $size items.
1455
 *
1456
 * @param array|Traversable $collection
1457
 * @param int $size
1458
 * @return bool
1459
 */
1460 View Code Duplication
function sizeIs($collection, $size)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1461
{
1462 1
    $itemsTempCount = 0;
1463
1464 1
    foreach ($collection as $key => $value) {
1465 1
        $itemsTempCount++;
1466
1467 1
        if ($itemsTempCount > $size) {
1468 1
            return false;
1469
        }
1470 1
    }
1471
1472 1
    return $itemsTempCount == $size;
1473
}
1474
1475
/**
1476
 * Checks whether $collection has less than $size items.
1477
 *
1478
 * @param array|Traversable $collection
1479
 * @param int $size
1480
 * @return bool
1481
 */
1482 View Code Duplication
function sizeIsLessThan($collection, $size)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1483
{
1484 1
    $itemsTempCount = 0;
1485
1486 1
    foreach ($collection as $key => $value) {
1487 1
        $itemsTempCount++;
1488
1489 1
        if ($itemsTempCount > $size) {
1490 1
            return false;
1491
        }
1492 1
    }
1493
1494 1
    return $itemsTempCount < $size;
1495
}
1496
1497
/**
1498
 * Checks whether $collection has more than $size items.
1499
 *
1500
 * @param array|Traversable $collection
1501
 * @param int $size
1502
 * @return bool
1503
 */
1504 View Code Duplication
function sizeIsGreaterThan($collection, $size)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1505
{
1506 1
    $itemsTempCount = 0;
1507
1508 1
    foreach ($collection as $key => $value) {
1509 1
        $itemsTempCount++;
1510
1511 1
        if ($itemsTempCount > $size) {
1512 1
            return true;
1513
        }
1514 1
    }
1515
1516 1
    return $itemsTempCount > $size;
1517
}
1518
1519
/**
1520
 * Checks whether $collection has between $fromSize to $toSize items. $toSize can be
1521
 * smaller than $fromSize.
1522
 *
1523
 * @param array|Traversable $collection
1524
 * @param int $fromSize
1525
 * @param int $toSize
1526
 * @return bool
1527
 */
1528
function sizeIsBetween($collection, $fromSize, $toSize)
1529
{
1530 1
    if ($fromSize > $toSize) {
1531 1
        $tmp = $toSize;
1532 1
        $toSize = $fromSize;
1533 1
        $fromSize = $tmp;
1534 1
    }
1535
1536 1
    $itemsTempCount = 0;
1537 1
    foreach ($collection as $key => $value) {
1538 1
        $itemsTempCount++;
1539
1540 1
        if ($itemsTempCount > $toSize) {
1541 1
            return false;
1542
        }
1543 1
    }
1544
1545 1
    return $fromSize < $itemsTempCount && $itemsTempCount < $toSize;
1546
}
1547
1548
/**
1549
 * Returns a sum of all values in the $collection.
1550
 *
1551
 * @param array|Traversable $collection
1552
 * @return int|float
1553
 */
1554
function sum($collection)
1555
{
1556 1
    $result = 0;
1557
1558 1
    foreach ($collection as $value) {
1559 1
        $result += $value;
1560 1
    }
1561
1562 1
    return $result;
1563
}
1564
1565
/**
1566
 * Returns average of values from $collection.
1567
 *
1568
 * @param array|Traversable $collection
1569
 * @return int|float
1570
 */
1571
function average($collection)
1572
{
1573 2
    $sum = 0;
1574 2
    $count = 0;
1575
1576 2
    foreach ($collection as $value) {
1577 1
        $sum += $value;
1578 1
        $count++;
1579 2
    }
1580
1581 2
    return $count ? $sum/$count : 0;
1582
}
1583
1584
/**
1585
 * Returns maximal value from $collection.
1586
 *
1587
 * @param array|Traversable $collection
1588
 * @return mixed
1589
 */
1590
function max($collection)
1591
{
1592 2
    $result = null;
1593
1594 2
    foreach ($collection as $value) {
1595 1
        $result = $value > $result ? $value : $result;
1596 2
    }
1597
1598 2
    return $result;
1599
}
1600
1601
/**
1602
 * Returns minimal value from $collection.
1603
 *
1604
 * @param array|Traversable $collection
1605
 * @return mixed
1606
 */
1607
function min($collection)
1608
{
1609 2
    $result = null;
1610 2
    $hasItem = false;
1611
1612 2
    foreach ($collection as $value) {
1613 1
        if (!$hasItem) {
1614 1
            $hasItem = true;
1615 1
            $result = $value;
1616 1
        }
1617
1618 1
        $result = $value < $result ? $value : $result;
1619 2
    }
1620
1621 2
    return $result;
1622
}
1623
1624
/**
1625
 * Returns a string by concatenating the $collection values into a string.
1626
 *
1627
 * @param array|Traversable $collection
1628
 * @return string
1629
 */
1630
function toString($collection)
1631
{
1632 1
    $result = '';
1633
1634 1
    foreach ($collection as $value) {
1635 1
        $result .= (string) $value;
1636 1
    }
1637
1638 1
    return $result;
1639
}
1640
1641
1642
/**
1643
 * Returns a lazy collection with items from $collection, but items with keys  that are found in keys of $replacementMap
1644
 * are replaced by their values.
1645
 *
1646
 * @param array|Traversable $collection
1647
 * @param array|Traversable $replacementMap
1648
 * @return Collection
1649
 */
1650 View Code Duplication
function replaceByKeys($collection, $replacementMap)
1 ignored issue
show
Duplication introduced by
This function seems to be duplicated in your project.

Duplicated code is one of the most pungent code smells. If you need to duplicate the same code in three or more different places, we strongly encourage you to look into extracting the code into a single class or operation.

You can also find more detailed suggestions in the “Code” section of your repository.

Loading history...
1651
{
1652
    $generatorFactory = function () use ($collection, $replacementMap) {
1653 1
        foreach ($collection as $key => $value) {
1654 1
            $newValue = getOrDefault($replacementMap, $key, $value);
1655 1
            yield $key => $newValue;
1656 1
        }
1657 1
    };
1658
1659 1
    return new Collection($generatorFactory);
1660
}
1661
1662
/**
1663
 * Dumps a variable into scalar or array (recursively).
1664
 *
1665
 * - scalars are returned as they are,
1666
 * - array of class name => properties (name => value and only properties accessible for this class)
1667
 *   is returned for objects,
1668
 * - arrays or Traversables are returned as arrays,
1669
 * - for anything else result of calling gettype($input) is returned
1670
 *
1671
 * If specified, $maxItemsPerCollection will only leave specified number of items in collection,
1672
 * appending a new element at end '>>>' if original collection was longer.
1673
 *
1674
 * If specified, $maxDepth will only leave specified n levels of nesting, replacing elements
1675
 * with '^^^' once the maximum nesting level was reached.
1676
 *
1677
 * If a collection with duplicate keys is encountered, the duplicate keys (except the first one)
1678
 * will be change into a format originalKey//duplicateCounter where duplicateCounter starts from
1679
 * 1 at the first duplicate. So [0 => 1, 0 => 2] will become [0 => 1, '0//1' => 2]
1680
 *
1681
 * @param mixed $input
1682
 * @param int|null $maxItemsPerCollection
1683
 * @param int|null $maxDepth
1684
 * @return array|mixed
1685
 */
1686
function dump($input, $maxItemsPerCollection = null, $maxDepth = null)
1687
{
1688 2
    if (is_scalar($input)) {
1689 2
        return $input;
1690
    }
1691
1692 2
    if (is_array($input) || $input instanceof Traversable) {
1693 2
        if ($maxDepth === 0) {
1694 1
            return '^^^';
1695
        }
1696
1697 2
        $normalizedProperties = [];
1698 2
        foreach ($input as $key => $value) {
1699 2
            if ($maxItemsPerCollection !== null && count($normalizedProperties) >= $maxItemsPerCollection) {
1700 2
                $normalizedProperties[] = '>>>';
1701 2
                break;
1702
            }
1703
1704 2
            for ($affix = 0; true; $affix++) {
1705 2
                $betterKey = $affix ? "$key//$affix" : $key;
1706 2
                if (!array_key_exists($betterKey, $normalizedProperties)) {
1707 2
                    $normalizedProperties[$betterKey] = dump(
1708 2
                        $value,
1709 2
                        $maxItemsPerCollection,
1710 2
                        $maxDepth>0 ? $maxDepth-1 : null
1711 2
                    );
1712
1713 2
                    break;
1714
                }
1715 1
            }
1716 2
        }
1717
1718 2
        return $normalizedProperties;
1719
    }
1720
1721 1
    if (is_object($input)) {
1722 1
        if ($maxDepth === 0) {
1723
            return '^^^';
1724
        }
1725
1726 1
        $reflection = new \ReflectionObject($input);
1727 1
        $normalizedProperties = [];
1728 1
        foreach ($reflection->getProperties() as $property) {
1729 1
            $property->setAccessible(true);
1730 1
            $normalizedProperties[$property->getName()] = $property->getValue($input);
1731 1
        }
1732 1
        return [get_class($input) => dump($normalizedProperties, null, $maxDepth>0 ? $maxDepth-1 : null)];
1733
    }
1734
1735
    return gettype($input);
1736
}
1737
1738
/**
1739
 * Calls dump on $input and then prints it using the var_export. Returns $input.
1740
 *
1741
 * @param mixed $input
1742
 * @param null|int $maxItemsPerCollection
1743
 * @param null|int $maxDepth
1744
 * @return mixed
1745
 */
1746
function printDump($input, $maxItemsPerCollection = null, $maxDepth = null)
1747
{
1748 1
    var_export(dump($input, $maxItemsPerCollection, $maxDepth));
1749 1
    return $input;
1750
}
1751