Laravel 5 Collections: Reducing a Collection to One Element With reduce

April 22, 2018 —John Koster

The reduce method is to reduce a collection into only one item. It does this by iterating over the collection and applying the $callback function on each element. The $callback function should define two parameters: $carry and $item. The $carry variable will be initialized to the previous result of the $callback function and the $item variable will contain the actual collection item relevant to the current iteration. The $reduce method also defines a $initial parameter.

Whatever value is given to $initial will become the value of the $carry variable on the first call to the $callback function. If there are no items in the collection, the $initial value is returned as the value of reduce.

The reduce method is similar in behavior to PHP's array_reduce function.

#Signature

1public function reduce(
2 callable $callback,
3 $initial = null
4);

#Example Use

The following examples will demonstrate some of the most basic uses of the reduce method. The returned value of the method call will appear above the method call as a comment.

1use Illuminate\Support\Collection;
2 
3// Create a new collection instance.
4$collection = new Collection([
5 1, 2, 3, 4, 5
6]);
7 
8// 15
9$sum = $collection->reduce(function($carry, $item) {
10 return $carry + $item;
11});
12 
13// -15
14$difference = $collection->reduce(function($carry, $item) {
15 return $carry - $item;
16});

The following sample will show how to get the product of each item in the collection. It will also prove a good use case for the $initial parameter:

1// 0
2$product = $collection->reduce(function($carry, $item) {
3 return $carry * $item;
4});

The above example returns 0 which might not seem obvious when the expected answer is 120. However, the $initial is used as the $carry argument for the first iteration of the $callback function. The $initial value is null by default. When null is used for mathematical operations in PHP, it is treated as the value 0:

1// 0
2$value = intval(null);

Because of this, the multiplication looks like this for each iteration (the result will become the carry value for the next iteration):

Iteration Carry Item Result
1 0 (from $initial) 1 0
2 0 2 0
3 0 3 0
4 0 4 0
5 0 5 0

The result is 0, because multiplying any value by zero will result in zero (the multiplication property of zero). To get the desired answer, the $initial value must be set to 1:

1// 120
2$product = $collection->reduce(function($carry, $item) {
3 return $carry * $item;
4}, 1);

The following table shows the iterations using the change made above:

Iteration Carry Item Result
1 1 (from $initial) 1 1
2 1 2 2
3 2 3 6
4 6 4 24
5 24 5 120

Some absolutely amazing
people

The following amazing people help support this site and my open source projects ♥️
If you're interesting in supporting my work and want to show up on this list, check out my GitHub Sponsors Profile.