Skip to main content

Aggregate Operations

An aggregate operation turns a whole collection into one value. Examples are the number of elements, their sum, the biggest element, or all elements combined into one result.

PHP gives you the common ones as built-in functions. count() counts the elements, min() and max() find the smallest and the biggest element, and array_sum() adds them up.

Be careful: min() and max() throw a ValueError on an empty array ("must contain at least one element"), and the program stops unless you catch it. Check count($s) > 0 first when the array might be empty. array_sum([]) is simply 0.

For combining elements one by one there is array_reduce($items, $callback, $initial). It keeps a running value, the accumulator, and calls your function with the accumulator and each element in turn. The accumulator starts as $initial — and when you leave $initial out, it starts as null, not as the first element. This page shows what that means and how to get both styles of combining, often called fold and reduce.


Basic Aggregates

The most common aggregates are count, minimum, maximum, sum and average.

  • count($numbers) gives the count.
  • min($numbers) and max($numbers) give the smallest and the biggest element. They work for numbers and strings.
  • array_sum($numbers) adds every element up. The average is the sum divided by the count. PHP's / keeps the decimal part when the division does not come out even, so 62 / 4 is 15.5.

Sometimes the smallest or biggest element should be picked by a rule, not by the value itself. min() and max() take no rule, but array_reduce() can keep the better element: at each step, compare the best element so far with the current one and keep the winner.

Sometimes every element must be converted with a function first and the results added up. Chain two built-ins: array_map() converts, array_sum() adds.

Count, min, max, sum and average

For the numbers 6, 42, 10 and 4 print the count with count(), the biggest and smallest element with max() and min(), and the sum with array_sum(). The average is 62 / 4 = 15.5.

Prompt
For the numbers 6, 42, 10 and 4 print the count with count(), the biggest and smallest element with max() and min(), the average as the sum divided by the count, and the sum with array_sum(). Label every line like "Count:", "Max:" and so on.
Output: PHP script
Count, min, max, sum and average

Min and max by a rule

The first array_reduce() keeps the element with the smaller remainder % 3. The remainders of 5, 42, 10 and 4 are 2, 0, 1 and 1, so 42 wins. The second keeps the longer string and finds "three". No initial value is given, so $best starts as null, and the $best === null check lets the first element win the first round. On a tie the earlier element stays.

Prompt
For the numbers 5, 42, 10 and 4 find the element whose remainder after dividing by 3 is the smallest, using array_reduce that keeps the better element (start from null). Then for the words one, two, three, four find the longest one the same way. Print both results.
Output: PHP script
Min and max by a rule

Sum of a function of each element

array_map() converts every element, array_sum() adds the results. Doubling 5, 42, 10 and 4 gives 122. Halving them gives 30.5.

Prompt
For the numbers 5, 42, 10 and 4 print the sum of every element doubled, then the sum of every element halved, each time with array_sum over array_map.
Output: PHP script
Sum of a function of each element

Fold and Reduce

Fold and reduce combine all elements into one value, step by step. They keep a running value called the accumulator. For each element they call a function with the accumulator and the element, and the function returns the new accumulator.

The difference is the starting value:

  • A fold starts with an initial value that you give it. The function runs once for every element. In PHP this is exactly array_reduce($items, $f, $initial).
  • A reduce starts with the first element. The function runs for the second element onward, so the first element is never passed through it.

Despite its name, array_reduce() is always a fold. Without a third argument it starts with null, and in arithmetic null counts as 0 — so the function still runs for every element. A real reduce takes the first element as the start and folds the rest: array_reduce(array_slice($items, 1), $f, $items[0]). A small reduce() helper wraps that line.

This matters when the function changes the element. If it doubles every element, a reduce leaves the first element as it is.

PHP has no reduce-from-the-right. To fold from the right, hand array_reduce() the reversed array from array_reverse(): the elements arrive last to first, and the function still gets the accumulator first and the element second.

Reduce

The reduce() helper takes 5 as the start and folds 2, 10 and 4 into it. The result is 21.

Prompt
Write a reduce helper that starts with the first element of an array and combines the rest into it with array_reduce over array_slice($items, 1) and the initial value $items[0]. Use it to add up the numbers 5, 2, 10 and 4 and print the result.
Output: PHP script
Reduce

Fold

array_reduce() with the initial value 0 starts at 0 and adds each element times 2. Every element is doubled: 10 + 4 + 20 + 8 = 42.

Prompt
Use array_reduce with the initial value 0 to add each of the numbers 5, 2, 10 and 4 times 2 to the accumulator. Print the result.
Output: PHP script
Fold

Fold versus Reduce

Both calls use the same function, accumulator plus element times 2. reduce() gives 37, because the first element 5 is the start and is not doubled. array_reduce() with the initial value 0 gives 42. Leaving out the 0 would also give 42: the start would be null, and null + 10 is 10.

Prompt
Write a reduce helper that starts with the first element (array_reduce over array_slice($items, 1) with $items[0] as the initial value). Define a function $addDoubled that returns $acc + $element * 2. Use it on the numbers 5, 2, 10 and 4 once with reduce() and once with array_reduce and the initial value 0, and print both results with the labels "Reduce:" and "Fold:".
Output: PHP script
Fold versus Reduce

Fold from the right

array_reverse($numbers) hands the elements to array_reduce() from the last one to the first. Addition does not care about the order, so the result is again 42.

Prompt
Use array_reduce with the initial value 0 over array_reverse($numbers) to add each of the numbers 5, 2, 10 and 4 times 2, walking from the last element to the first. Print the result.
Output: PHP script
Fold from the right

Fold with Index

Sometimes the position of an element matters, not only its value.

The callback of array_reduce() never sees the keys, but a plain foreach loop does. foreach ($numbers as $idx => $element) walks from the start. array_reverse($numbers, true) reverses the array but keeps the original keys, because the second argument is true — so a foreach over it walks from the end and still sees each element's real index. Inside the loop an if checks the index and decides whether to add the element.

Fold with index

Only the elements at even indexes are added: index 0 holds 5 and index 2 holds 10, so the sum is 15.

Prompt
Add up only the elements of 5, 2, 10, 4 that sit at an even index. Use a foreach loop with the index and an if on the index. Print the sum.
Output: PHP script
Fold with index

Fold with index from the right

The same rule, but the loop starts at index 3 and goes down to 0. The result is still 15.

Prompt
Add up only the elements of 5, 2, 10, 4 that sit at an even index, walking from the last index down to 0 with a foreach over array_reverse($numbers, true), which keeps the original keys. Print the sum.
Output: PHP script
Fold with index from the right

Safe Reduce

A reduce needs a first element to start with. On an empty array the reduce() helper would read $items[0], which does not exist: PHP prints a warning ("Undefined array key 0") and carries on with null.

The PHP way to say "there is no result" is null. A small helper checks the array first: when it is empty, it returns null without touching $items[0]. The caller then checks for null, just like $map[$key] ?? $default handles a missing key. array_reduce() itself already behaves this way: on an empty array it returns its initial value, which is null when you give none.

Reduce or null

reduceOrNull() returns 21 for the numbers 5, 2, 10 and 4, and null for an empty array. The last line shows that array_reduce() without an initial value also returns null for an empty array. json_encode() prints null as the word null.

Prompt
Write a function reduceOrNull that returns null for an empty array and otherwise starts with the first element and folds the rest in with array_reduce. Call it with an add function on the numbers 5, 2, 10 and 4 and on an empty array. Then call array_reduce on the empty array without an initial value. Print all three results with json_encode.
Output: PHP script
Reduce or null

Running Fold and Reduce

A running fold or reduce does not throw away the steps in between. It saves the accumulator after every element, so the result is an array of all the running values.

PHP has no built-in function for this. Keep a sum variable and append it to a result array with $result[] = $sum inside a foreach loop. For a running reduce the result starts with the first element. For a running fold the result starts with the initial value and has one more element than the input.

Running reduce

The numbers 0 to 5 are added one by one. The result array holds every sum along the way: 0, 1, 3, 6, 10, 15.

Prompt
For the numbers 0 to 5, start a sum with the first element and add the rest one by one in a foreach loop, saving every running sum in a result array that starts with the first element. Print the result with implode.
Output: PHP script
Running reduce

Running fold

The same with the initial value 10. The result begins with 10 itself and has one more element than the input: 10, 10, 11, 13, 16, 20, 25.

Prompt
For the numbers 0 to 5, start a sum at the initial value 10 and add every element one by one in a foreach loop, saving every running sum in a result array that starts with 10. Print the result with implode.
Output: PHP script
Running fold