Skip to content

Commit 9c36d06

Browse files
[8.x] Add reduceMany to Collections (#39078)
* [8.x] Add `reduceMany` to Collections * StyleCI * StyleCI * Update EnumeratesValues.php Co-authored-by: Taylor Otwell <[email protected]>
1 parent 698029e commit 9c36d06

File tree

2 files changed

+63
-0
lines changed

2 files changed

+63
-0
lines changed

src/Illuminate/Collections/Traits/EnumeratesValues.php

Lines changed: 28 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -15,6 +15,7 @@
1515
use JsonSerializable;
1616
use Symfony\Component\VarDumper\VarDumper;
1717
use Traversable;
18+
use UnexpectedValueException;
1819

1920
/**
2021
* @property-read HigherOrderCollectionProxy $average
@@ -744,6 +745,33 @@ public function reduce(callable $callback, $initial = null)
744745
return $result;
745746
}
746747

748+
/**
749+
* Reduce the collection to multiple aggregate values.
750+
*
751+
* @param callable $callback
752+
* @param mixed ...$initial
753+
* @return array
754+
*
755+
* @throws \UnexpectedValueException
756+
*/
757+
public function reduceMany(callable $callback, ...$initial)
758+
{
759+
$result = $initial;
760+
761+
foreach ($this as $key => $value) {
762+
$result = call_user_func_array($callback, array_merge($result, [$value, $key]));
763+
764+
if (! is_array($result)) {
765+
throw new UnexpectedValueException(sprintf(
766+
"%s::reduceMany expects reducer to return an array, but got a '%s' instead.",
767+
class_basename(static::class), gettype($result)
768+
));
769+
}
770+
}
771+
772+
return $result;
773+
}
774+
747775
/**
748776
* Reduce an associative collection to a single value.
749777
*

tests/Support/SupportCollectionTest.php

Lines changed: 35 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -22,6 +22,7 @@
2222
use ReflectionClass;
2323
use stdClass;
2424
use Symfony\Component\VarDumper\VarDumper;
25+
use UnexpectedValueException;
2526

2627
class SupportCollectionTest extends TestCase
2728
{
@@ -3902,6 +3903,40 @@ public function testReduceWithKeys($collection)
39023903
}));
39033904
}
39043905

3906+
/**
3907+
* @dataProvider collectionClassProvider
3908+
*/
3909+
public function testReduceMany($collection)
3910+
{
3911+
$data = new $collection([-1, 0, 1, 2, 3, 4, 5]);
3912+
3913+
[$sum, $max, $min] = $data->reduceMany(function ($sum, $max, $min, $value) {
3914+
$sum += $value;
3915+
$max = max($max, $value);
3916+
$min = min($min, $value);
3917+
3918+
return [$sum, $max, $min];
3919+
}, 0, PHP_INT_MIN, PHP_INT_MAX);
3920+
3921+
$this->assertEquals(14, $sum);
3922+
$this->assertEquals(5, $max);
3923+
$this->assertEquals(-1, $min);
3924+
}
3925+
3926+
/**
3927+
* @dataProvider collectionClassProvider
3928+
*/
3929+
public function testReduceManyThrowsAnExceptionIfReducerDoesNotReturnAnArray($collection)
3930+
{
3931+
$data = new $collection([1]);
3932+
3933+
$this->expectException(UnexpectedValueException::class);
3934+
3935+
$data->reduceMany(function () {
3936+
return false;
3937+
}, null);
3938+
}
3939+
39053940
/**
39063941
* @dataProvider collectionClassProvider
39073942
*/

0 commit comments

Comments
 (0)