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
Push — master ( 5a47e3...6784a9 )
by Dušan
03:31
created

collection_functions.php ➔ replaceByKeys()   A

Complexity

Conditions 2
Paths 1

Size

Total Lines 11
Code Lines 6

Duplication

Lines 11
Ratio 100 %

Code Coverage

Tests 6
CRAP Score 2

Importance

Changes 0
Metric Value
cc 2
eloc 6
c 0
b 0
f 0
nc 1
nop 2
dl 11
loc 11
ccs 6
cts 6
cp 1
crap 2
rs 9.4285
1
<?php
2
3
namespace DusanKasan\Knapsack;
4
5
use DusanKasan\Knapsack\Exceptions\ItemNotFound;
6
use DusanKasan\Knapsack\Exceptions\NoMoreItems;
7
use Traversable;
8
9
/**
10
     * Converts $collection to array. If there are multiple items with the same key, only the last will be preserved.
11
 *
12
 * @param array|Traversable $collection
13
 * @return array
14
 */
15
function toArray($collection)
16
{
17 64
    $arr = [];
18 64
    foreach ($collection as $key => $value) {
19 64
        $arr[$key] = $value;
20 64
    }
21
22 64
    return $arr;
23
}
24
25
/**
26
 * Returns a lazy collection of distinct items in $collection.
27
 *
28
 * @param array|Traversable $collection
29
 * @return Collection
30
 */
31
function distinct($collection)
32
{
33
    $generatorFactory = function () use ($collection) {
34 1
        $distinctValues = [];
35
36 1
        foreach ($collection as $key => $value) {
37 1
            if (!in_array($value, $distinctValues)) {
38 1
                $distinctValues[] = $value;
39 1
                yield $key => $value;
40 1
            }
41 1
        }
42 1
    };
43
44 1
    return new Collection($generatorFactory);
45
}
46
47
/**
48
 * Returns number of items in $collection.
49
 *
50
 * @param array|Traversable $collection
51
 * @return int
52
 */
53
function size($collection)
54
{
55 8
    $result = 0;
56 8
    foreach ($collection as $value) {
57 8
        $result++;
58 8
    }
59
60 8
    return $result;
61
}
62
63
/**
64
 * Returns a non-lazy collection with items from $collection in reversed order.
65
 *
66
 * @param array|Traversable $collection
67
 * @return Collection
68
 */
69
function reverse($collection)
70
{
71
    $generatorFactory = function () use ($collection) {
72 4
        $array = [];
73 4
        foreach ($collection as $key => $value) {
74 3
            $array[] = [$key, $value];
75 4
        }
76
77 4
        return map(
78 5
            indexBy(
79 4
                array_reverse($array),
80
                function($item) {
81 3
                    return $item[0];
82
                }
83 4
            ),
84
            function($item) {
85 3
                return $item[1];
86
            }
87 4
        );
88 4
    };
89
90 4
    return new Collection($generatorFactory);
91
}
92
93
/**
94
 * Returns a lazy collection of values from $collection (i.e. the keys are reset).
95
 *
96
 * @param array|Traversable $collection
97
 * @return Collection
98
 */
99
function values($collection)
100
{
101
    $generatorFactory = function () use ($collection) {
102 32
        foreach ($collection as $value) {
103 30
            yield $value;
104 26
        }
105 32
    };
106
107 32
    return new Collection($generatorFactory);
108
}
109
110
/**
111
 * Returns a lazy collection of keys from $collection.
112
 *
113
 * @param array|Traversable $collection
114
 * @return Collection
115
 */
116
function keys($collection)
117
{
118
    $generatorFactory = function () use ($collection) {
119 1
        foreach ($collection as $key => $value) {
120 1
            yield $key;
121 1
        }
122 1
    };
123
124 1
    return new Collection($generatorFactory);
125
}
126
127
/**
128
 * Returns a lazy collection of items from $collection repeated infinitely.
129
 *
130
 * @param array|Traversable $collection
131
 * @return Collection
132
 */
133
function cycle($collection)
134
{
135
    $generatorFactory = function () use ($collection) {
136 1
        while (true) {
137 1
            foreach ($collection as $key => $value) {
138 1
                yield $key => $value;
139 1
            }
140 1
        }
141 1
    };
142
143 1
    return new Collection($generatorFactory);
144
}
145
146
/**
147
 * Returns a non-lazy collection of shuffled items from $collection.
148
 *
149
 * @param array|Traversable $collection
150
 * @return Collection
151
 */
152
function shuffle($collection)
153
{
154 1
    $buffer = [];
155 1
    foreach ($collection as $key => $value) {
156 1
        $buffer[] = [$key, $value];
157 1
    }
158
159 1
    \shuffle($buffer);
160
161 1
    return dereferenceKeyValue($buffer);
162
}
163
164
/**
165
 * Returns true if $collection does not contain any items.
166
 *
167
 * @param array|Traversable $collection
168
 * @return bool
169
 */
170
function isEmpty($collection)
171
{
172 3
    foreach ($collection as $value) {
173 1
        return false;
174 2
    }
175
176 2
    return true;
177
}
178
179
/**
180
 * Returns true if $collection does contain any items.
181
 *
182
 * @param array|Traversable $collection
183
 * @return bool
184
 */
185
function isNotEmpty($collection)
186
{
187 2
    return !isEmpty($collection);
188
}
189
190
/**
191
 * Returns a collection where keys are distinct values from $collection and values are number of occurrences of each
192
 * value.
193
 *
194
 * @param array|Traversable $collection
195
 * @return Collection
196
 */
197
function frequencies($collection)
198
{
199 1
    return countBy($collection, '\DusanKasan\Knapsack\identity');
200
}
201
202
/**
203
 * Returns the first item of $collection or throws ItemNotFound if #collection is empty.
204
 *
205
 * @param array|Traversable $collection
206
 * @return mixed
207
 */
208
function first($collection)
209
{
210 13
    return get(values($collection), 0);
211
}
212
213
/**
214
 * Returns the last item of $collection or throws ItemNotFound if #collection is empty.
215
 *
216
 * @param array|Traversable $collection
217
 * @return mixed
218
 */
219
function last($collection)
220
{
221 2
    return first(reverse($collection));
222
}
223
224
/**
225
 * Returns a lazy collection of items of $collection where value of each item is set to the return value of calling
226
 * $function on its value and key.
227
 *
228
 * @param array|Traversable $collection
229
 * @param callable $function ($value, $key)
230
 * @return Collection
231
 */
232 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...
233
{
234
    $generatorFactory = function () use ($collection, $function) {
235 15
        foreach ($collection as $key => $value) {
236 14
            yield $key => $function($value, $key);
237 14
        }
238 15
    };
239
240 15
    return new Collection($generatorFactory);
241
}
242
243
/**
244
 * Returns a lazy collection of items from $collection for which $function returns true.
245
 *
246
 * @param array|Traversable $collection
247
 * @param callable|null $function ($value, $key)
248
 * @return Collection
249
 */
250
function filter($collection, callable $function = null)
251
{
252 7
    if (null === $function) {
253
        $function = function ($value) {
254 1
            return (bool)$value;
255 1
        };
256 1
    };
257
258
    $generatorFactory = function () use ($collection, $function) {
259 7
        foreach ($collection as $key => $value) {
260 7
            if ($function($value, $key)) {
261 5
                yield $key => $value;
262 5
            }
263 7
        }
264 7
    };
265
266 7
    return new Collection($generatorFactory);
267
}
268
269
/**
270
 * Returns a lazy collection with items from all $collections passed as argument appended together
271
 *
272
 * @param array|Traversable ...$collections
273
 * @return Collection
274
 */
275
function concat(...$collections)
276
{
277
    $generatorFactory = function () use ($collections) {
278 4
        foreach ($collections as $collection) {
279 4
            foreach ($collection as $key => $value) {
280 4
                yield $key => $value;
281 4
            }
282 4
        }
283 4
    };
284
285 4
    return new Collection($generatorFactory);
286
}
287
288
/**
289
 * Reduces the collection to single value by iterating over the collection and calling $reduction while
290
 * passing $startValue and current key/item as parameters. The output of $function is used as $startValue in
291
 * next iteration. The output of $function on last element is the return value of this function.
292
 *
293
 * @param array|Traversable $collection
294
 * @param callable $function ($value, $key)
295
 * @param mixed $startValue
296
 * @return mixed
297
 */
298
function reduce($collection, callable $function, $startValue)
299
{
300 3
    $tmp = duplicate($startValue);
301
302 3
    foreach ($collection as $key => $value) {
303 3
        $tmp = $function($tmp, $value, $key);
304 3
    }
305
306 3
    return $tmp;
307
}
308
309
/**
310
 * Flattens multiple levels of nesting in collection. If $levelsToFlatten is not specified, flattens all levels of
311
 * nesting.
312
 *
313
 * @param array|Traversable $collection
314
 * @param int $levelsToFlatten -1 to flatten everything
315
 * @return Collection
316
 */
317
function flatten($collection, $levelsToFlatten = -1)
318
{
319
    $generatorFactory = function () use ($collection, $levelsToFlatten) {
320 3
        $flattenNextLevel = $levelsToFlatten < 0 || $levelsToFlatten > 0;
321 3
        $childLevelsToFlatten = $levelsToFlatten > 0 ? $levelsToFlatten - 1 : $levelsToFlatten;
322
323 3
        foreach ($collection as $key => $value) {
324 3
            if ($flattenNextLevel && (is_array($value) || $value instanceof Traversable)) {
325 3
                foreach (flatten($value, $childLevelsToFlatten) as $childKey => $childValue) {
326 3
                    yield $childKey => $childValue;
327 3
                }
328 3
            } else {
329 3
                yield $key => $value;
330
            }
331 3
        }
332 3
    };
333
334 3
    return new Collection($generatorFactory);
335
}
336
337
/**
338
 * Returns a non-lazy collection sorted using $collection($item1, $item2, $key1, $key2 ). $collection should
339
 * return true if first item is larger than the second and false otherwise.
340
 *
341
 * @param array|Traversable $collection
342
 * @param callable $function ($value1, $value2, $key1, $key2)
343
 * @return Collection
344
 */
345
function sort($collection, callable $function)
346
{
347 2
    $array = iterator_to_array(
348 2
        values(
349 2
            map(
350 2
                $collection,
351
                function ($value, $key) {
352 2
                    return [$key, $value];
353
                }
354 2
            )
355 2
        )
356 2
    );
357
358 2
    uasort(
359 2
        $array,
360
        function ($a, $b) use ($function) {
361 2
            return $function($a[1], $b[1], $a[0], $b[0]);
362
        }
363 2
    );
364
365 2
    return dereferenceKeyValue($array);
366
}
367
368
/**
369
 * Returns a lazy collection that is a part of $collection starting from $from position and ending in $to position.
370
 * If $to is not provided, the returned collection is contains all items from $from until end of $collection. All items
371
 * before $from are iterated over, but not included in result.
372
 *
373
 * @param array|Traversable $collection
374
 * @param int $from
375
 * @param int $to -1 to slice until end
376
 * @return Collection
377
 */
378
function slice($collection, $from, $to = -1)
379
{
380
    $generatorFactory = function () use ($collection, $from, $to) {
381 15
        $index = 0;
382 15
        foreach ($collection as $key => $value) {
383 15
            if ($index >= $from && ($index < $to || $to == -1)) {
384 15
                yield $key => $value;
385 15
            } elseif ($index >= $to && $to >= 0) {
386 12
                break;
387
            }
388
389 15
            $index++;
390 15
        }
391 15
    };
392
393 15
    return new Collection($generatorFactory);
394
}
395
396
/**
397
 * Returns a non-lazy collection of items grouped by the result of $function.
398
 *
399
 * @param array|Traversable $collection
400
 * @param callable $function ($value, $key)
401
 * @return Collection
402
 */
403
function groupBy($collection, callable $function)
404
{
405 4
    $result = [];
406
407 4
    foreach ($collection as $key => $value) {
408 4
        $newKey = $function($value, $key);
409
410 4
        $group = isset($result[$newKey]) ? $result[$newKey] : new Collection([]);
411 4
        $result[$newKey] = $group->append($value);
412 4
    }
413
414 4
    return Collection::from($result);
415
}
416
417
418
/**
419
 * Returns a non-lazy collection of items grouped by the value at given key. Ignores non-collection items and items
420
 * without the given keys
421
 *
422
 * @param array|Traversable $collection
423
 * @param mixed $key
424
 * @return Collection
425
 */
426
function groupByKey($collection, $key)
427
{
428
    $generatorFactory = function () use ($collection, $key) {
429
430 1
        return groupBy(
431 1
            filter(
432 1
                $collection,
433
                function ($item) use ($key) {
434 1
                    return isCollection($item) && has($item, $key);
435
                }
436 1
            ),
437
            function($value) use ($key) {
438 1
                return get($value, $key);
439
            }
440 1
        );
441 1
    };
442
443 1
    return new Collection($generatorFactory);
444
}
445
/**
446
 * Executes $function for each item in $collection
447
 *
448
 * @param array|Traversable $collection
449
 * @param callable $function ($value, $key)
450
 * @return Collection
451
 */
452 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...
453
{
454
    $generatorFactory = function () use ($collection, $function) {
455 1
        foreach ($collection as $key => $value) {
456 1
            $function($value, $key);
457
458 1
            yield $key => $value;
459 1
        }
460 1
    };
461
462 1
    return new Collection($generatorFactory);
463
}
464
465
/**
466
 * Returns an item with $key key from $collection. If that key is not present, throws ItemNotFound.
467
 *
468
 * @param array|Traversable $collection
469
 * @param mixed $key
470
 * @return mixed
471
 */
472
function get($collection, $key)
473
{
474 20
    foreach ($collection as $valueKey => $value) {
475 18
        if ($key === $valueKey) {
476 17
            return $value;
477
        }
478 16
    }
479
480 9
    throw new ItemNotFound;
481
}
482
483
/**
484
 * Returns an item with $key key from $collection. If that key is not present, returns $default.
485
 *
486
 * @param array|Traversable $collection
487
 * @param mixed $key
488
 * @param mixed $default value returned if key is not found
489
 * @return mixed
490
 */
491
function getOrDefault($collection, $key, $default)
492
{
493
    try {
494 3
        return get($collection, $key);
495 3
    } catch (ItemNotFound $e) {
496 3
        return $default;
497
    }
498
}
499
500
/**
501
 * Returns the first item from $collection for which $function returns true. If item like that is not present, returns
502
 * $default.
503
 *
504
 * @param array|Traversable $collection
505
 * @param callable $function ($value, $key)
506
 * @param mixed $default
507
 * @return mixed
508
 */
509
function find($collection, callable $function, $default = null)
510
{
511 1
    foreach ($collection as $key => $value) {
512 1
        if ($function($value, $key)) {
513 1
            return $value;
514
        }
515 1
    }
516
517 1
    return $default;
518
}
519
520
/**
521
 * Returns a lazy collection by changing keys of $collection for each item to the result of $function for
522
 * that item.
523
 *
524
 * @param array|Traversable $collection
525
 * @param callable $function ($value, $key)
526
 * @return Collection
527
 */
528 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...
529
{
530
    $generatorFactory = function () use ($collection, $function) {
531 5
        foreach ($collection as $key => $value) {
532 4
            yield $function($value, $key) => $value;
533 4
        }
534 5
    };
535
536 5
    return new Collection($generatorFactory);
537
}
538
539
/**
540
 * Returns a non-lazy collection of items whose keys are the return values of $function and values are the number of
541
 * items in this collection for which the $function returned this value.
542
 *
543
 * @param array|Traversable $collection
544
 * @param callable $function ($value, $key)
545
 * @return Collection
546
 */
547
function countBy($collection, callable $function)
548
{
549 2
    return map(
550 2
        groupBy($collection, $function),
551
        '\DusanKasan\Knapsack\size'
552 2
    );
553
}
554
555
/**
556
 * Returns true if $function returns true for every item in $collection
557
 *
558
 * @param array|Traversable $collection
559
 * @param callable $function ($value, $key)
560
 * @return bool
561
 */
562
function every($collection, callable $function)
563
{
564 1
    foreach ($collection as $key => $value) {
565 1
        if (!$function($value, $key)) {
566 1
            return false;
567
        }
568 1
    }
569
570 1
    return true;
571
}
572
573
/**
574
 * Returns true if $function returns true for at least one item in $collection.
575
 *
576
 * @param array|Traversable $collection
577
 * @param callable $function ($value, $key)
578
 * @return bool
579
 */
580
function some($collection, callable $function)
581
{
582 1
    foreach ($collection as $key => $value) {
583 1
        if ($function($value, $key)) {
584 1
            return true;
585
        }
586 1
    }
587
588 1
    return false;
589
}
590
591
/**
592
 * Returns true if $needle is found in $collection values.
593
 *
594
 * @param $collection
595
 * @param mixed $needle
596
 * @return bool
597
 */
598
function contains($collection, $needle)
599
{
600 1
    foreach ($collection as $key => $value) {
601 1
        if ($value === $needle) {
602 1
            return true;
603
        }
604 1
    }
605
606 1
    return false;
607
}
608
609
/**
610
 * Reduce that walks from right to the left.
611
 *
612
 * @param array|Traversable $collection
613
 * @param callable $function
614
 * @param mixed $startValue
615
 * @return mixed
616
 */
617
function reduceRight($collection, callable $function, $startValue)
618
{
619 1
    return reduce(reverse($collection), $function, $startValue);
620
}
621
622
/**
623
 * Returns a lazy collection of first $numberOfItems items of $collection.
624
 *
625
 * @param array|Traversable $collection
626
 * @param int $numberOfItems
627
 * @return Collection
628
 */
629
function take($collection, $numberOfItems)
630
{
631 12
    return slice($collection, 0, $numberOfItems);
632
}
633
634
/**
635
 * Returns a lazy collection of all but first $numberOfItems items of $collection.
636
 *
637
 * @param array|Traversable $collection
638
 * @param int $numberOfItems
639
 * @return Collection
640
 */
641
function drop($collection, $numberOfItems)
642
{
643 4
    return slice($collection, $numberOfItems);
644
}
645
646
/**
647
 * Returns a lazy collection of values, where first value is $value and all subsequent values are computed by applying
648
 * $function to the last value in the collection. By default this produces an infinite collection. However you can
649
 * end the collection by throwing a NoMoreItems exception.
650
 *
651
 * @param mixed $value
652
 * @param callable $function ($value, $key)
653
 * @return Collection
654
 */
655
function iterate($value, callable $function)
656
{
657 4
    $duplicated = duplicate($value);
658
    $generatorFactory = function () use ($duplicated, $function) {
659 4
        $value = $duplicated;
660
661 4
        yield $value;
662
663 4
        while (true) {
664
            try {
665 4
                $value = $function($value);
666 4
                yield $value;
667 4
            } catch (NoMoreItems $e) {
668 2
                break;
669
            }
670 4
        }
671 4
    };
672
673 4
    return new Collection($generatorFactory);
674
}
675
676
/**
677
 * Returns a lazy collection of items from $collection for which $function returned true.
678
 *
679
 * @param array|Traversable $collection
680
 * @param callable $function ($value, $key)
681
 * @return Collection
682
 */
683
function reject($collection, callable $function)
684
{
685 2
    return filter(
686 2
        $collection,
687
        function($value, $key) use ($function) {
688 2
            return !$function($value, $key);
689
        }
690 2
    );
691
}
692
693
/**
694
 * Returns a lazy collection of items in $collection without the last $numberOfItems items.
695
 *
696
 * @param array|Traversable $collection
697
 * @param int $numberOfItems
698
 * @return Collection
699
 */
700
function dropLast($collection, $numberOfItems = 1)
701
{
702
    $generatorFactory = function () use ($collection, $numberOfItems) {
703 1
        $buffer = [];
704
705 1
        foreach ($collection as $key => $value) {
706 1
            $buffer[] = [$key, $value];
707
708 1
            if (count($buffer) > $numberOfItems) {
709 1
                $val = array_shift($buffer);
710 1
                yield $val[0] => $val[1];
711 1
            }
712 1
        }
713 1
    };
714
715 1
    return new Collection($generatorFactory);
716
}
717
718
/**
719
 * Returns a lazy collection of items from $collection separated by $separator.
720
 *
721
 * @param array|Traversable $collection
722
 * @param mixed $separator
723
 * @return Collection
724
 */
725
function interpose($collection, $separator)
726
{
727
    $generatorFactory = function () use ($collection, $separator) {
728 1
        foreach (take($collection, 1) as $key => $value) {
729 1
            yield $key => $value;
730 1
        }
731
732 1
        foreach (drop($collection, 1) as $key => $value) {
733 1
            yield $separator;
734 1
            yield $key => $value;
735 1
        }
736 1
    };
737
738 1
    return new Collection($generatorFactory);
739
}
740
741
/**
742
 * Returns a lazy collection of first item from first collection, first item from second, second from first and
743
 * so on. Accepts any number of collections.
744
 *
745
 * @param array|Traversable ...$collections
746
 * @return Collection
747
 */
748
function interleave(...$collections)
749
{
750
    $generatorFactory = function () use ($collections) {
751 1
        $normalizedCollection = array_map(
752
            function ($collection) {
753 1
                $traversable = new Collection($collection);
754 1
                $traversable->rewind();
755 1
                return $traversable;
756 1
            },
757
            $collections
758 1
        );
759
760
        do {
761 1
            $valid = false;
762 1
            foreach ($normalizedCollection as $collection) {
763 1
                if ($collection->valid()) {
764 1
                    yield $collection->key() => $collection->current();
765 1
                    $collection->next();
766 1
                    $valid = true;
767 1
                }
768 1
            }
769 1
        } while ($valid);
770 1
    };
771
772 1
    return new Collection($generatorFactory);
773
}
774
775
/**
776
 * Returns a lazy collection of items in $collection with $value added as first element. If $key is not provided
777
 * it will be next integer index.
778
 *
779
 * @param array|Traversable $collection
780
 * @param mixed $value
781
 * @param mixed|null $key
782
 * @return Collection
783
 */
784 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...
785
{
786
    $generatorFactory = function () use ($collection, $value, $key) {
787 2
        if ($key === null) {
788 1
            yield $value;
789 1
        } else {
790 1
            yield $key => $value;
791
        }
792
793 2
        foreach ($collection as $key => $value) {
794 2
            yield $key => $value;
795 2
        }
796 2
    };
797
798 2
    return new Collection($generatorFactory);
799
}
800
801
/**
802
 * Returns a lazy collection of items in $collection with $value added as last element. If $key is not provided
803
 * it will be next integer index.
804
 *
805
 * @param array|Traversable $collection
806
 * @param mixed $value
807
 * @param mixed|null $key
808
 * @return Collection
809
 */
810 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...
811
{
812
    $generatorFactory = function () use ($collection, $value, $key) {
813 11
        foreach ($collection as $k => $v) {
814 11
            yield $k => $v;
815 11
        }
816
817 11
        if ($key === null) {
818 9
            yield $value;
819 9
        } else {
820 2
            yield $key => $value;
821
        }
822 11
    };
823
824 11
    return new Collection($generatorFactory);
825
}
826
827
/**
828
 * Returns a lazy collection by removing items from $collection until first item for which $function returns false.
829
 *
830
 * @param array|Traversable $collection
831
 * @param callable $function ($value, $key)
832
 * @return Collection
833
 */
834 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...
835
{
836
    $generatorFactory = function () use ($collection, $function) {
837 2
        $shouldDrop = true;
838 2
        foreach ($collection as $key => $value) {
839 2
            if ($shouldDrop) {
840 2
                $shouldDrop = $function($value, $key);
841 2
            }
842
843 2
            if (!$shouldDrop) {
844 2
                yield $key => $value;
845 2
            }
846 2
        }
847 2
    };
848
849 2
    return new Collection($generatorFactory);
850
}
851
852
/**
853
 * Returns a lazy collection of items from $collection until first item for which $function returns false.
854
 *
855
 * @param array|Traversable $collection
856
 * @param callable $function ($value, $key)
857
 * @return Collection
858
 */
859 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...
860
{
861
    $generatorFactory = function () use ($collection, $function) {
862 2
        $shouldTake = true;
863 2
        foreach ($collection as $key => $value) {
864 2
            if ($shouldTake) {
865 2
                $shouldTake = $function($value, $key);
866 2
            }
867
868 2
            if ($shouldTake) {
869 2
                yield $key => $value;
870 2
            }
871 2
        }
872 2
    };
873
874 2
    return new Collection($generatorFactory);
875
}
876
877
/**
878
 * Returns a lazy collection. A result of calling map and flatten(1)
879
 *
880
 * @param array|Traversable $collection
881
 * @param callable $function ($value, $key)
882
 * @return Collection
883
 */
884
function mapcat($collection, callable $function)
885
{
886 1
    return flatten(map($collection, $function), 1);
887
}
888
889
/**
890
 * Returns a lazy collection [take($collection, $position), drop($collection, $position)]
891
 *
892
 * @param array|Traversable $collection
893
 * @param int $position
894
 * @return Collection
895
 */
896
function splitAt($collection, $position)
897
{
898
    $generatorFactory = function () use ($collection, $position) {
899 1
        yield take($collection, $position);
900 1
        yield drop($collection, $position);
901 1
    };
902
903 1
    return new Collection($generatorFactory);
904
}
905
906
/**
907
 * Returns a lazy collection [takeWhile($collection, $function), dropWhile($collection, $function)]
908
 *
909
 * @param array|Traversable $collection
910
 * @param callable $function ($value, $key)
911
 * @return Collection
912
 */
913
function splitWith($collection, callable $function)
914
{
915
    $generatorFactory = function () use ($collection, $function) {
916 1
        yield takeWhile($collection, $function);
917 1
        yield dropWhile($collection, $function);
918 1
    };
919
920 1
    return new Collection($generatorFactory);
921
}
922
923
/**
924
 * Returns a lazy collection with items from $collection but values that are found in keys of $replacementMap
925
 * are replaced by their values.
926
 *
927
 * @param array|Traversable $collection
928
 * @param array|Traversable $replacementMap
929
 * @return Collection
930
 */
931 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...
932
{
933
    $generatorFactory = function () use ($collection, $replacementMap) {
934 1
        foreach ($collection as $key => $value) {
935 1
            $newValue = getOrDefault($replacementMap, $value, $value);
936 1
            yield $key => $newValue;
937 1
        }
938 1
    };
939
940 1
    return new Collection($generatorFactory);
941
}
942
943
/**
944
 * Returns a lazy collection of reduction steps.
945
 *
946
 * @param array|Traversable $collection
947
 * @param callable $function
948
 * @param mixed $startValue
949
 * @return Collection
950
 */
951 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...
952
{
953
    $generatorFactory = function () use ($collection, $function, $startValue) {
954 1
        $tmp = duplicate($startValue);
955
956 1
        yield $tmp;
957 1
        foreach ($collection as $key => $value) {
958 1
            $tmp = $function($tmp, $value, $key);
959 1
            yield $tmp;
960 1
        }
961 1
    };
962
963 1
    return new Collection($generatorFactory);
964
}
965
966
/**
967
 * Returns a lazy collection of every nth ($step) item in  $collection.
968
 *
969
 * @param array|Traversable $collection
970
 * @param int $step
971
 * @return Collection
972
 */
973
function takeNth($collection, $step)
974
{
975
    $generatorFactory = function () use ($collection, $step) {
976 1
        $index = 0;
977 1
        foreach ($collection as $key => $value) {
978 1
            if ($index % $step == 0) {
979 1
                yield $key => $value;
980 1
            }
981
982 1
            $index++;
983 1
        }
984 1
    };
985
986 1
    return new Collection($generatorFactory);
987
}
988
989
/**
990
 * Returns a lazy collection of collections of $numberOfItems items each, at $step step
991
 * apart. If $step is not supplied, defaults to $numberOfItems, i.e. the partitions
992
 * do not overlap. If a $padding collection is supplied, use its elements as
993
 * necessary to complete last partition up to $numberOfItems items. In case there are
994
 * not enough padding elements, return a partition with less than $numberOfItems items.
995
 *
996
 * @param array|Traversable $collection
997
 * @param $numberOfItems
998
 * @param int $step
999
 * @param array|Traversable $padding
1000
 * @return Collection
1001
 */
1002
function partition($collection, $numberOfItems, $step = -1, $padding = [])
1003
{
1004
    $generatorFactory = function () use ($collection, $numberOfItems, $step, $padding) {
1005 1
        $buffer = [];
1006 1
        $itemsToSkip = 0;
1007 1
        $tmpStep = $step ?: $numberOfItems;
1008
1009 1
        foreach ($collection as $key => $value) {
1010 1
            if (count($buffer) == $numberOfItems) {
1011 1
                yield dereferenceKeyValue($buffer);
1012
1013 1
                $buffer = array_slice($buffer, $tmpStep);
1014 1
                $itemsToSkip =  $tmpStep - $numberOfItems;
1015 1
            }
1016
1017 1
            if ($itemsToSkip <= 0) {
1018 1
                $buffer[] = [$key, $value];
1019 1
            } else {
1020 1
                $itemsToSkip--;
1021
            }
1022 1
        }
1023
1024 1
        yield take(
1025 1
            concat(dereferenceKeyValue($buffer), $padding),
1026
            $numberOfItems
1027 1
        );
1028 1
    };
1029
1030 1
    return new Collection($generatorFactory);
1031
}
1032
1033
/**
1034
 * Returns a lazy collection created by partitioning $collection each time $function returned a different value.
1035
 *
1036
 * @param array|Traversable $collection
1037
 * @param callable $function
1038
 * @return Collection
1039
 */
1040
function partitionBy($collection, callable $function)
1041
{
1042
    $generatorFactory = function () use ($collection, $function) {
1043 1
        $result = null;
1044 1
        $buffer = [];
1045
1046 1
        foreach ($collection as $key => $value) {
1047 1
            $newResult = $function($value, $key);
1048
1049 1
            if (!empty($buffer) && $result != $newResult) {
1050 1
                yield dereferenceKeyValue($buffer);
1051 1
                $buffer = [];
1052 1
            }
1053
1054 1
            $result = $newResult;
1055 1
            $buffer[] = [$key, $value];
1056 1
        }
1057
1058 1
        if (!empty($buffer)) {
1059 1
            yield dereferenceKeyValue($buffer);
1060 1
        }
1061 1
    };
1062
1063 1
    return new Collection($generatorFactory);
1064
}
1065
1066
/**
1067
 * Returns a lazy collection of $value repeated $times times. If $times is not provided the collection is infinite.
1068
 *
1069
 * @param mixed $value
1070
 * @param int $times
1071
 * @return Collection
1072
 */
1073
function repeat($value, $times = -1)
1074
{
1075
    $generatorFactory = function () use ($value, $times) {
1076 3
        $tmpTimes = $times;
1077
1078 3
        while ($tmpTimes != 0) {
1079 3
            yield $value;
1080
1081 3
            $tmpTimes = $tmpTimes < 0 ? -1 : $tmpTimes - 1;
1082 3
        }
1083 3
    };
1084
1085 3
    return new Collection($generatorFactory);
1086
}
1087
1088
/**
1089
 * Returns a lazy collection of numbers starting at $start, incremented by $step until $end is reached.
1090
 *
1091
 * @param int $start
1092
 * @param int|null $end
1093
 * @param int $step
1094
 * @return Collection
1095
 */
1096
function range($start = 0, $end = null, $step = 1)
1097
{
1098
    $generatorFactory = function () use ($start, $end, $step) {
1099 2
        return iterate(
1100 2
            $start,
1101
            function($value) use ($step, $end) {
1102 2
                $result = $value + $step;
1103
1104 2
                if ($end !== null && $result > $end) {
1105 1
                    throw new NoMoreItems;
1106
                }
1107
1108 2
                return $result;
1109
            }
1110 2
        );
1111 2
    };
1112
1113 2
    return new Collection($generatorFactory);
1114
}
1115
1116
/**
1117
 * Returns true if $input is array or Traversable object.
1118
 *
1119
 * @param mixed $input
1120
 * @return bool
1121
 */
1122
function isCollection($input)
1123
{
1124 18
    return is_array($input) || $input instanceof Traversable;
1125
}
1126
1127
/**
1128
 * Returns duplicated/cloned $input that has no relation to the original one. Used for making sure there are no side
1129
 * effect in functions.
1130
 *
1131
 * @param $input
1132
 * @return mixed
1133
 */
1134
function duplicate($input)
1135
{
1136 8
    if (is_array($input)) {
1137 1
        return toArray(
1138 1
            map(
1139 1
                $input,
1140
                function($i) {
1141 1
                    return duplicate($i);
1142
                }
1143 1
            )
1144 1
        );
1145 8
    } elseif (is_object($input)) {
1146 2
        return clone $input;
1147
    } else {
1148 8
        return $input;
1149
    }
1150
}
1151
1152
/**
1153
 * Transforms [[$key, $value], [$key2, $value2]] into [$key => $value, $key2 => $value2]. Used as a helper
1154
 *
1155
 * @param array|Traversable $collection
1156
 * @return Collection
1157
 */
1158
function dereferenceKeyValue($collection)
1159
{
1160
    $generatorFactory = function () use ($collection) {
1161 6
        foreach ($collection as $value) {
1162 6
            yield $value[0] => $value[1];
1163 6
        }
1164 7
    };
1165
1166 7
    return new Collection($generatorFactory);
1167
}
1168
1169
/**
1170
 * Realizes collection - turns lazy collection into non-lazy one by iterating over it and storing the key/values.
1171
 *
1172
 * @param array|Traversable $collection
1173
 * @return Collection
1174
 */
1175
function realize($collection)
1176
{
1177 1
    return dereferenceKeyValue(
1178 1
        toArray(
1179 1
            map(
1180 1
                $collection,
1181
                function ($value, $key) {
1182 1
                    return [$key, $value];
1183
                }
1184 1
            )
1185 1
        )
1186 1
    );
1187
}
1188
1189
/**
1190
 * Returns the second item of $collection or throws ItemNotFound if $collection is empty or has 1 item.
1191
 *
1192
 * @param array|Traversable $collection
1193
 * @return mixed
1194
 */
1195
function second($collection)
1196
{
1197 6
    return get(values($collection), 1);
1198
}
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);
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
 * Returns a lazy collection of data extracted from $collection items by dot separated key path. Supports the *
1389
 * wildcard. If a key contains \ or * it must be escaped using \ character.
1390
 *
1391
 * @param array|Traversable $collection
1392
 * @param mixed $keyPath
1393
 * @return Collection
1394
 */
1395
function extract($collection, $keyPath)
1396
{
1397 1
    preg_match_all('/(.*[^\\\])(?:\.|$)/U', $keyPath, $matches);
1398 1
    $pathParts = $matches[1];
1399
1400
    $extractor = function ($coll) use ($pathParts) {
1401 1
        foreach ($pathParts as $pathPart) {
1402 1
            $coll = flatten(filter($coll, '\DusanKasan\Knapsack\isCollection'), 1);
1403
1404 1
            if ($pathPart != '*') {
1405 1
                $pathPart = str_replace(['\.', '\*'], ['.', '*'], $pathPart);
1406 1
                $coll = values(only($coll, [$pathPart]));
1407 1
            }
1408 1
        }
1409
1410 1
        return $coll;
1411 1
    };
1412
1413
    $generatorFactory = function () use ($collection, $extractor) {
1414 1
        foreach ($collection as $item) {
1415 1
            foreach ($extractor([$item]) as $extracted) {
1416 1
                yield $extracted;
1417 1
            }
1418 1
        }
1419 1
    };
1420
1421
1422 1
    return new Collection($generatorFactory);
1423
}
1424
1425
/**
1426
 * Checks whether $collection has exactly $size items.
1427
 *
1428
 * @param array|Traversable $collection
1429
 * @param int $size
1430
 * @return bool
1431
 */
1432 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...
1433
{
1434 1
    $itemsTempCount = 0;
1435
1436 1
    foreach ($collection as $key => $value) {
1437 1
        $itemsTempCount++;
1438
1439 1
        if ($itemsTempCount > $size) {
1440 1
            return false;
1441
        }
1442 1
    }
1443
1444 1
    return $itemsTempCount == $size;
1445
}
1446
1447
/**
1448
 * Checks whether $collection has less than $size items.
1449
 *
1450
 * @param array|Traversable $collection
1451
 * @param int $size
1452
 * @return bool
1453
 */
1454 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...
1455
{
1456 1
    $itemsTempCount = 0;
1457
1458 1
    foreach ($collection as $key => $value) {
1459 1
        $itemsTempCount++;
1460
1461 1
        if ($itemsTempCount > $size) {
1462 1
            return false;
1463
        }
1464 1
    }
1465
1466 1
    return $itemsTempCount < $size;
1467
}
1468
1469
/**
1470
 * Checks whether $collection has more than $size items.
1471
 *
1472
 * @param array|Traversable $collection
1473
 * @param int $size
1474
 * @return bool
1475
 */
1476 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...
1477
{
1478 1
    $itemsTempCount = 0;
1479
1480 1
    foreach ($collection as $key => $value) {
1481 1
        $itemsTempCount++;
1482
1483 1
        if ($itemsTempCount > $size) {
1484 1
            return true;
1485
        }
1486 1
    }
1487
1488 1
    return $itemsTempCount > $size;
1489
}
1490
1491
/**
1492
 * Checks whether $collection has between $fromSize to $toSize items. $toSize can be
1493
 * smaller than $fromSize.
1494
 *
1495
 * @param array|Traversable $collection
1496
 * @param int $fromSize
1497
 * @param int $toSize
1498
 * @return bool
1499
 */
1500
function sizeIsBetween($collection, $fromSize, $toSize)
1501
{
1502 1
    if ($fromSize > $toSize) {
1503 1
        $tmp = $toSize;
1504 1
        $toSize = $fromSize;
1505 1
        $fromSize = $tmp;
1506 1
    }
1507
1508 1
    $itemsTempCount = 0;
1509 1
    foreach ($collection as $key => $value) {
1510 1
        $itemsTempCount++;
1511
1512 1
        if ($itemsTempCount > $toSize) {
1513 1
            return false;
1514
        }
1515 1
    }
1516
1517 1
    return $fromSize < $itemsTempCount && $itemsTempCount < $toSize;
1518
}
1519
1520
/**
1521
 * Returns a sum of all values in the $collection.
1522
 *
1523
 * @param array|Traversable $collection
1524
 * @return int|float
1525
 */
1526
function sum($collection)
1527
{
1528 1
    $result = 0;
1529
1530 1
    foreach ($collection as $value) {
1531 1
        $result += $value;
1532 1
    }
1533
1534 1
    return $result;
1535
}
1536
1537
/**
1538
 * Returns average of values from $collection.
1539
 *
1540
 * @param array|Traversable $collection
1541
 * @return int|float
1542
 */
1543
function average($collection)
1544
{
1545 2
    $sum = 0;
1546 2
    $count = 0;
1547
1548 2
    foreach ($collection as $value) {
1549 1
        $sum += $value;
1550 1
        $count++;
1551 2
    }
1552
1553 2
    return $count ? $sum/$count : 0;
1554
}
1555
1556
/**
1557
 * Returns maximal value from $collection.
1558
 *
1559
 * @param array|Traversable $collection
1560
 * @return mixed
1561
 */
1562
function max($collection)
1563
{
1564 2
    $result = null;
1565
1566 2
    foreach ($collection as $value) {
1567 1
        $result = $value > $result ? $value : $result;
1568 2
    }
1569
1570 2
    return $result;
1571
}
1572
1573
/**
1574
 * Returns minimal value from $collection.
1575
 *
1576
 * @param array|Traversable $collection
1577
 * @return mixed
1578
 */
1579
function min($collection)
1580
{
1581 2
    $result = null;
1582 2
    $hasItem = false;
1583
1584 2
    foreach ($collection as $value) {
1585 1
        if (!$hasItem) {
1586 1
            $hasItem = true;
1587 1
            $result = $value;
1588 1
        }
1589
1590 1
        $result = $value < $result ? $value : $result;
1591 2
    }
1592
1593 2
    return $result;
1594
}
1595
1596
/**
1597
 * Returns a string by concatenating the $collection values into a string.
1598
 *
1599
 * @param array|Traversable $collection
1600
 * @return string
1601
 */
1602
function toString($collection)
1603
{
1604 1
    $result = '';
1605
1606 1
    foreach ($collection as $value) {
1607 1
        $result .= (string) $value;
1608 1
    }
1609
1610 1
    return $result;
1611
}
1612
1613
1614
/**
1615
 * Returns a lazy collection with items from $collection, but items with keys  that are found in keys of $replacementMap
1616
 * are replaced by their values.
1617
 *
1618
 * @param array|Traversable $collection
1619
 * @param array|Traversable $replacementMap
1620
 * @return Collection
1621
 */
1622 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...
1623
{
1624
    $generatorFactory = function () use ($collection, $replacementMap) {
1625 1
        foreach ($collection as $key => $value) {
1626 1
            $newValue = getOrDefault($replacementMap, $key, $value);
1627 1
            yield $key => $newValue;
1628 1
        }
1629 1
    };
1630
1631 1
    return new Collection($generatorFactory);
1632
}
1633