`reduce`

just [recursively] combines a data structure into a new value: that value can be anything.

So for example, reimplementing some of the JS array methods (and adding some other common ones):

The normal example, using it to take an array of numbers and sum them, returning a single value: `sum([1,2,3,4])`

returns `10`

```
function sum(arr) {
return reduce((a,b) => a + b, 0);
}
```

`reverse`

returns a reversed version of the input array (non-mutating version of `Array.prototype.reverse`

). So `reverse([1,2,3,4])`

returns `[4,3,2,1]`

.

```
function reverse(arr) {
return arr.reduce((acc, v) => [v, ... acc], []);
}
```

Do the same as `Array.prototype.map`

- so `map([1,2,3,4], (x) => x ** 2)`

returns `[1,4,9,16]`

.

```
function map(arr, fn) {
return arr.reduce((acc, v) => {
return acc.concat(fn(v));
}, []);
}
```

Flattens an array of arrays to a single array, same as `Array.prototype.flat`

- so `flatten([[1],[2],[3],[4]])`

returns `[1,2,3,4]`

.

```
function flatten(arr) {
return reduce((acc, arr) => [...acc, ...arr], [])
}
```

That only works for one level of nesting, so could take an array of arrays of any depth and flatten to one array: so `flattenDeep([1,[2,[3,4]]])`

returns `[1,2,3,4]`

.

```
function flattenDeep(arr) {
return arr.reduce((acc, v) => {
if (Array.isArray(v)) {
return acc.concat(flatten(v));
} else {
return acc.concat(v);
}
}, []);
}
```

Joins an array into a string with a given joining string - same as `Array.prototype.join`

, so `join([1,2,3,4], ' ')`

returns `'1 2 3 4'`

.

```
function join(arr, joiner = ',') {
return arr.reduce((acc, v, index) => {
if (index == 0) {
return `${v}`
} else {
return `${acc}${joiner}${v}`;
}
}, '');
}
```

Given an array, returns an array with an item inserted between each of the original values, so `intersperse([1,2,3,4], 'hi')`

returns`[1, 'hi', 2, 'hi', 3, 'hi', 4]`

.

```
function intersperse(arr, item) {
return arr.reduce((acc, v, index) => {
if (index == 0) {
return [v]
} else {
return acc.concat([item, v]);
}
}, []);
}
```

Filter and map on the same array, first function you pass is the filter, then anything that gets through that gets mapped - so `filterMap([1,2,3,4], (x) => x % 2 === 0, (x) => x ** 2)`

returns `[4, 16]`

```
function filterMap(arr, filter, mapper) {
return arr.reduce((acc, v) => {
if (filter(v)) {
return acc.concat(mapper(v));
} else {
return acc;
}
}, []);
}
```