Esse tal de Reduce e como podemos usar.
Published: 2021-03-29 14:31:57

---
title: Esse tal de Reduce e como podemos usar.
published: true
description: 
tags: 
cover_image: https://i.postimg.cc/x19SS1FX/javascript-reduce.png
---

O Reduce é utilizado em um array, iterando em cada item até retornar um único valor. Ele recebe uma função e um valor inicial. Essa função recebe 4 argumentos:

- a variável que servirá como acumulador
- o elemento atual
- o index
- o array original

```jsx
array.reduce(function(accumulator, element, index, array) => {}, initialValue; 
```

```jsx
const data = [1, 2, 3, 4, 5]
const reducer = function(accumulator, item) {
	return accumulator + item
}
const initialValue = 0;
const total = data.reduce(reducer, initialValue) // 15
```

```jsx
const votes = ["angular", "angular", "react", "react", "react","vue", "ember", "vanilla"]
const initialValue = {};
const reducer = function(poll, vote) {
	if(!poll[vote]) {
		poll[vote] = 1
	} else {
		poll[vote] = poll[vote] + 1
	}

	return poll;
}
const totalVotes = votes.reduce(reducer, initialValue)
```

## Reduce e performance

Vamos ver dois exemplos com funções que utilizamos diariamente e como o uso do reduce pode ser útil.

Dado um array, iremos retornar um novo array com a mesma quantidade de itens sendo que seus valores são o dobro do valor inicial.

```jsx
const data = [1, 2, 3, 4, 5, 6]
const initialValue = [];
const reducer = function(total, value){
	total.push(value * 2)
	return total;
}

const doubled = data.reduce(reducer, initialValue)
```

Esse mesmo resultado pode ser alcançado utilizando Map, inclusive com menos linhas.

Um outro caso seria filtrar o mesmo array, retornando apenas os números pares.

```jsx
const data = [1, 2, 3, 4, 5, 6]
const initialValue = [];
const reducer = function(total, value){
	if(value % 2 === 0) {
		total.push(value)
	}
	return value;
}
const odd = data.reduce(reducer, initialValue)
console.log(odd)
```

Nesse segundo caso podemos utilizar o filter, que como o próprio nome diz, irá filtrar o array retornando o valor que desejamos.

Inclusive esses métodos podem ser utilizados em conjunto, para filtrar e retornar os números pares com valor dobrado.

Tendo isso em mente e ainda possuindo um código bem mais enxuto de se escrever, porque optaríamos por utilizar o reducer para realizar essa operação?

Nos exemplos utilizados, foram usados arrays pequenos, controlados. Mas qual seria o resultado disso em arrays muito maiores? Vamos comparar.

```jsx
let bigData = []
for(let i = 0; i<1000000; i++) {
	bigData[i] = i
}

console.time('filteredMapped')
const filteredMapped = bigData.filter(value => value % 2 === 0)
.map(value => value * 2)
console.timeEnd('filteredMapped')

console.time('reducer')
const reducer = bigData.reduce(function(acc, value){
	if(value % 2 === 0) {
		acc.push(value * 2)
	}
	return acc
}, [])
console.timeEnd('reducer')
```

Notou a diferença no tempo de execução das funções? Se tratando de lidar com muitas informações, podemos ter um considerável ganho de performance mesmo tendo que escrever algumas linhas a mais.

A lógica utilizada é a mesma, mas onde temos um ganho é que no primeiro caso é necessário que o método filter passe por todas os 1000000 itens, para só depois o map realizar sua operação nos 500000 restantes.

Enquanto com o uso do reduce essa operação é realizada de uma única vez, nos itens que filtramos.

## Atenção a possíveis erros

```jsx
const votes = ["angular", "angular", "react", "react", "react","vue", "ember", "vanilla"]
const initialValue = {};
const reducer = function(poll, vote) {
	if(!poll[vote]) {
		poll[vote] = 1
	} else {
		poll[vote] = poll[vote] + 1
	}

	return poll;
}
const totalVotes = votes.reduce(reducer)
```

Esse foi o primeiro exemplo que utilizamos aqui, mas dessa vez ao executarmos temos um resultado diferente:

```jsx
console.log(totalVotes) // 'angular'
```

O que será que aconteceu aqui? Notou alguma diferença na função desse exemplo e o anterior?

O problema é que esquecemos de informar o valor initial(`initialValue`) para o nosso reduce.

Tá, mas nesse caso não era para ter dado erro na execução? Sim... e não!

Na intenção de nos ajudar o Javascript percebe que nenhum valor inicial foi informado e assume que o primeiro item do array é esse valor. Sendo a string 'angular', um valor primitivo ele não recebe propriedades e por suas vez seu valor é falso. No final, o valor inicial é retornado.

Um outro possível caso, é esquecermos de retornar o accumulator ao final do reduce e com isso o retorno acaba sendo `undefined`.