PHP Array Reduce function
Tags: programming, php, array, beginners
Published: 2023-02-02 13:02:13

## Table of Contents

- [About Array Reduce](#about-array-reduce)
- [Simple example](#simple-example)
- [Practical example](#practical-example)
- [Try the code](#try-the-code)
- [Use cases](#use-cases)

## About Array Reduce

`array_reduce` is an array function that iteratively reduces an array to a single value by applying a callback function to elements in the array.

```php
array_reduce(
  array $array, 
  callable $callback, 
  mixed $initial = null
): mixed
```

It takes the following parameters:

- an array (what do we want to reduce),
- callback (the logic),
- initial value(for example, an empty array []).

## Simple example:

Let's find unique values in array.

#### 1. We have an array of products

```php
// an array
$products = [
  "shirt",
  "shoes",
  "shirt"
];
```

#### 2. A callback function, which checks if an item is already in an array.

```php
$reducer = function ($all, $item) {
  if (!in_array($item, $all)) {
    array_push($all, $item);
  }
  return $all;
};
```

- The variable `$item` holds the value of the current iteration of `$products.`
- The variable `$all` holds the return value of the previous iteration. Its initial value is defined as the last parameter in `array_reduce.`

#### 3. initial value

Since we return an array in the callback, the type must match the initial array (we define an empty array as the initial value).

```php
$initial = [];
```

#### array_reduce()

```php
$products = [
  "shirt",
  "shoes",
  "shirt"
];

$reducer = function ($all, $item) {
  if (!in_array($item, $all)) {
    array_push($all, $item);
  }
  return $all;
};

$initial = [];

array_reduce($products, $reducer, $initial);

// this will return
// [
//   "shirt",
//   "shoes",
// ]
```

##### if we pass some initial values

```php
array_reduce($products, $reducer, ["hat"]);

// this will return
// [
//   "hat",
//   "shirt",
//   "shoes",
// ]
```

##### also, everything in one place:

```php 
array_reduce(
  ["shirt", "shoes", "shirt"],    // an array to reduce
  function ($all, $item) {        // callback
    if (!in_array($item, $all)) {
      array_push($all, $item);
    }
    return $all;
  },
  []                              // initial
);
```

***Obviously, we can use `array_unique($products)` instead to achieve the same results in this example.***

## Practical example:

Let's say we have an array of products(key, value structure).

```php
$products = [
  ["name" => "Product 1", "price" => 10],
  ["name" => "Product 1", "price" => 10],
  ["name" => "Product 1", "price" => 10],
  ["name" => "Product 2", "price" => 2],
  ["name" => "Product 3", "price" => 7],
  ["name" => "Product 2", "price" => 2],
];
```

And we need to create an array where we count the same products (`$quantity`) and sum their price (`$total`) like this:

```php
[
  "Product 1" => [
    "total" => ...,
    "quantity" => ...,
  ],
  "Product 2" => [
    "total" => ...,
    "quantity" => ...,
  ],
  ...
]
```

we can use an array_reduce function:

```php
array_reduce($products, $reducer, []);
```

where we pass `$products` and an empty array as initial value. all we need is to write the callback.

then, in the callback:

1. since `$item` is a key-value pair (["name" => "Product 1", "price" => 10]) for simplicity, we assign the name and its price to variables.

2. We check if the item is in the array ($all):

- if there is one with the same key, we increase its quantity by 1 and add the price.
- if not, we push the item to $all and set its quantity to 1.

```php
$products = [
  ["name" => "Product 1", "price" => 10],
  ["name" => "Product 1", "price" => 10],
  ["name" => "Product 1", "price" => 10],
  ["name" => "Product 2", "price" => 2],
  ["name" => "Product 3", "price" => 7],
  ["name" => "Product 2", "price" => 2],
];

$reducer = function ($all, $item) {
  $name = $item["name"];
  $price = $item["price"];
  if (isset($all[$name])) {
    $all[$name]["quantity"]++;
    $all[$name]["total"] += $price;
  } else {
    $all[$name]["total"] = $price;
    $all[$name]["quantity"] = 1;
  }
  return $all;
};

array_reduce($products, $reducer, []);

// and that will return:
// [
//   "Product 1" => [
//     "total" => 30,
//     "quantity" => 3,
//   ],
//   "Product 2" => [
//     "total" => 4,
//     "quantity" => 2,
//   ],
//   "Product 3" => [
//     "total" => 7,
//     "quantity" => 1,
//   ],
// ]
```

## Try the code:

https://replit.com/@stafura/arrayreduce-in-PHP#main.php

## Use cases:

There are many ways you can use the array_reduce function, such as:

- summing up all the elements of an array,
- flattening a nested array,
- grouping elements based on some criterion,
- counting the occurrences of items in an array,
- filtering an array based on some condition.

more info:
https://www.php.net/manual/en/function.array-reduce.php