Code Snippets: Array.prototype.reduce()
Tags: codesnippets, javascript
Published: 2022-07-06 18:49:54

## What is Array.prototype.reduce()?
The reduce method runs a callback function on each item of an array, passing in the value that was returned by the previous.

The previous value on the first call will be the item at index 0, unless otherwise provided in the method call.

### Syntax

```js
Array.prototype.reduce((prev, curr) => newValue)
// or
Array.prototype.reduce((prev, curr) => newValue, initialValue)
```

## Examples
### Get Sum of Numbers
Here we add the current item to the value returned by the last.

```js
const numbers = [1, 2, 3, 4, 5];

const sum = numbers.reduce((acc, curr) => acc + curr); 
// 15
```

### Get Max of Numbers
Instead of returning the previous value added to the current value like we did with the sum example, we simply return the larger of the two.

```js
const numbers = [1, 2, 3, 4, 5];

const max = numbers.reduce((acc, curr) => (acc > curr ? acc : curr)); 
// 5
```

This can be applied to an array of objects too.

```js
const people = [
	{ name: "John", age: 20 },
	{ name: "Jane", age: 21 },
	{ name: "Joe", age: 22 },
	{ name: "Jack", age: 23 },
	{ name: "Jill", age: 24 },
	{ name: "Juan", age: 25 },
];

const oldestPerson = people.reduce((oldest, current) =>
	current.age > oldest.age ? current : oldest
);
// { name: "Juan", age: 25 }
```

### Combine Filter and Map
Sometimes we need to filter data, and then map that data to a new shape or type. However, we can do both of those things with reduce.

In doing so, we avoid the need to traverse the array twice.

```js
const people = [
	{
		firstName: "John",
		lastName: "Doe",
		age: 20,
	},
	{
		firstName: "Jane",
		lastName: "Doe",
		age: 21,
	},
	{
		firstName: "Joe",
		lastName: "Doe",
		age: 22,
	},
	{
		firstName: "Jack",
		lastName: "Doe",
		age: 23,
	},
	{
		firstName: "Jill",
		lastName: "Doe",
		age: 24,
	},
	{
		firstName: "Juan",
		lastName: "Doe",
		age: 25,
	},
];


const canDrink = people.reduce(
	(drinkers, curr) =>
		curr.age >= 21
			? [...drinkers, `${curr.firstName} ${curr.lastName}`]
			: drinkers,
	[]
);
// [ "Jane Doe", "Joe Doe", "Jack Doe", "Jill Doe", "Juan Doe" ]
```
We did pass an initial value this time because we are creating an array, if we did not pass `[]` then the function would try and call .push on a person object which would cause an uncaught TypeError.

We can also accomplish this without copying the drinkers array each time.

```js
const canDrink = people.reduce((drinkers, curr) => {
	if (curr.age >= 21) {
		drinkers.push(`${curr.firstName} ${curr.lastName}`);
	}
	return drinkers;
}, []);
```

In comparison, this would be the same effect with map and filter:

```js
const canDrink = people
	.filter((person) => person.age >= 21)
	?.map((person) => `${person.firstName} ${person.lastName}`);
```
### Convert Array to Object
We can easily convert an array to an object, in this case a dictionary of week days and their respective number value.

For this specific example we will accept an optional 3rd parameter for the index in our callback function.
```js
const days = [
	"Sunday",
	"Monday",
	"Tuesday",
	"Wednesday",
	"Thursday",
	"Friday",
	"Saturday",
];

const daysOfWeek = days.reduce((newDays, day, index) => {
	newDays[day] = index;
	return newDays;
}, {});
// { Sunday: 0, Monday: 1, Tuesday: 2, Wednesday: 3, Thursday: 4, Friday: 5, Saturday: 6 }
```

### Change Object Shape
We can also change the shape of an object to fit our needs.

```js
const coordinates = {
	lat1: 0,
	lon1: 0,
	lat2: 31.968599,
	lon2: -99.9018131,
	lat3: 26.820553,
	lon3: -80.053407,
	lat4: 25.774252,
	lon4: -80.193665,
};

const parsedCoordinates = Object.keys(coordinates).reduce(
	(acc, key) => {
		const value = coordinates[key];
		if (key?.includes("lat")) {
			acc["lat"].push(value);
		} else {
			acc["lon"].push(value);
		}
		return acc;
	},
	{ lat: [], lon: [] }
);
/**
{
  lat: [ 0, 31.968599, 26.820553, 25.774252 ],
  lon: [ 0, -99.9018131, -80.053407, -80.193665 ]
}
*/`
```

## Conclusion
Overall the reduce method can make your work a lot easier if you know how to use it!