Esta página foi traduzida do inglês pela comunidade.Saiba mais e junte-se à comunidade MDN Web Docs.
Array.prototype.reduce()
Baseline Widely available
This feature is well established and works across many devices and browser versions. It’s been available across browsers since julho de 2015.
O métodoreduce() executa uma funçãoreducer (fornecida por você) para cada elemento do array, resultando num único valor de retorno.
In this article
Experimente
const array1 = [1, 2, 3, 4];// 0 + 1 + 2 + 3 + 4const initialValue = 0;const sumWithInitial = array1.reduce( (accumulator, currentValue) => accumulator + currentValue, initialValue,);console.log(sumWithInitial);// Expected output: 10A funçãoreducer recebe quatro parâmetros:
- Acumulador (
acc) - Valor Atual (
cur) - Index Atual (
idx) - Array original (
src)
O valor de retorno da sua funçãoreducer é atribuída ao acumulador. O acumulador, com seu valor atualizado, é repassado para cada iteração subsequente pelo array, que por fim, se tornará o valor resultante, único, final.
Sintaxe
array.reduce(callback( acumulador, valorAtual[, index[, array]] )[, valorInicial])Parâmetros
callbackFunção que é executada em cada valor no array (exceto no primeiro, se nenhum
valorInicialfor passado); recebe quatro argumentos:acumuladorÉ o valor inicial (ou o valor do callback anterior). Este valor inicia com o
valorIniciale será retornado na última iteração.valorAtualOpcional. O índice do elemento atual que está sendo processado no array. Começa a partir do index
0se umvalorInicialfor fornecido. Do contrário, começa do index1.valorInicialOpcional. Valor a ser usado como o primeiro argumento da primeira chamada da função
callback. Se nenhumvalorInicialé fornecido, o primeiro elemento do array será usado como o valor inicial doacumuladore ovalorAtualnão será lido. Chamarreduce()em uma array vazia sem valor inicial retornará um erro.
Valor retornado
O valor que resulta da execução da função de callback do "reducer" até a conclusão de todo o array.
Descrição
O métodoreduce() executa a função decallback uma vez para cada elemento presente no array, excluindo furos (valores indefinidos), recebendo quatro argumentos:
- acumulador - valor inicial (ou o valor do callback anterior),
- valorAtual - o valor do elemento atual
- index - o índice atual e
array- o array onde a iteração está ocorrendo.
A primeira vez que o callback é chamado, oacumulador e ovalorAtual podem ter um de dois valores possíveis. Se ovalorInicial tiver sido fornecido na chamada à funçãoreduce(), então oacumulador será igual aovalorInicial e ovalorAtual será igual ao primeiro valor no array. Caso nenhumvalorInicial seja fornecido,acumulador será igual ao primeiro valor no array, evalorAtual será igual ao segundo.
Nota:Se ovalorInicial não tiver sido passado como argumento, então reduce() executará o callback da função começando a partir do índice 1 (index 1), pulando o primeiro índice (index 0). Se ovalorInicial for passado como argumento, a função irá começar no index 0.
Se a array estiver vazia e ovalorInicial não tiver sido informado, uma exceção do tipoTypeError será lançada.
Se a array possuir somente um elemento (independente da posição) e ovalorInicial não tiver sido fornecido, ou sevalorInicial for fornecido, mas a array estiver vazia, o valor será retornado sem que a função decallback seja chamada.
É mais seguro prover umvalorInicial, porque existem atéquatro possíveis saídas sem ovalorInicial, como mostrado no exemplo:
var maxCallback = (acc, cur) => Math.max(acc.x, cur.x);var maxCallback2 = (max, cur) => Math.max(max, cur);// reduce() sem valores iniciais[{ x: 22 }, { x: 42 }].reduce(maxCallback); // 42[{ x: 22 }].reduce(maxCallback); // { x: 22 }[].reduce(maxCallback); // TypeError// map/reduce; melhor solução, funciona para vetores vazios e tambem para vetores grandes[{ x: 22 }, { x: 42 }].map((el) => el.x).reduce(maxCallback2, -Infinity);Como funciona o reduce()
Suponha que o seguinte uso de reduce() tenha ocorrido:
[0, 1, 2, 3, 4].reduce(function (acumulador, valorAtual, index, array) { return acumulador + valorAtual;});// 10O callback será invocado quatro vezes, com os argumentos e valores em cada chamada sendo:
acumulador | valorAtual | index | array | valor de retorno | |
|---|---|---|---|---|---|
| primeira chamada | 0 | 1 | 1 | [0, 1, 2, 3, 4] | 1 |
| segunda chamada | 1 | 2 | 2 | [0, 1, 2, 3, 4] | 3 |
| terceira chamada | 3 | 3 | 3 | [0, 1, 2, 3, 4] | 6 |
| quarta chamada | 6 | 4 | 4 | [0, 1, 2, 3, 4] | 10 |
O valor retornado peloreduce será o da última chamada à callback(10).
Você também pode usar umaArrow Function em vez de uma função completa. O código abaixo produz a mesma saída que o código do bloco acima:
[0, 1, 2, 3, 4].reduce((accum, curr) => accum + curr);Se você informar umvalorInicial como o segundo argumento de reduce, o resultado será:
[0, 1, 2, 3, 4].reduce(function (acumulador, valorAtual, indice, array) { return acumulador + valorAtual;}, 10);// 20callback | acumulador | valorAtual | index | array | valor de retorno |
|---|---|---|---|---|---|
| primeira chamada | 10 | 0 | 0 | [0, 1, 2, 3, 4] | 10 |
| segunda chamada | 10 | 1 | 1 | [0, 1, 2, 3, 4] | 11 |
| terceira chamada | 11 | 2 | 2 | [0, 1, 2, 3, 4] | 13 |
| quarta chamada | 13 | 3 | 3 | [0, 1, 2, 3, 4] | 16 |
| quinta chamada | 16 | 4 | 4 | [0, 1, 2, 3, 4] | 20 |
O retorno da última chamada20,é retornado como resultado da funçãoreduce().
Exemplos
>Soma todos os valores de uma array
let total = [0, 1, 2, 3].reduce(function (acumulador, valorAtual) { return acumulador + valorAtual;}, 0);// retorna 6outra alternativa é usar uma arrow function:
var total = [0, 1, 2, 3].reduce( (acumulador, valorAtual) => acumulador + valorAtual, 0,);Soma de valores de um objeto de um array
Para resumir os valores contidos em um array, vocêdeve fornecer umvalorInicial, para que cada item passe por sua função.
var valorInicial = 0;var soma = [{ x: 1 }, { x: 2 }, { x: 3 }].reduce(function ( acumulador, valorAtual,) { return acumulador + valorAtual.x;}, valorInicial);console.log(soma); // retorna 6Utilizando uma arrow function:
var valorInicial = 0;var soma = [{ x: 1 }, { x: 2 }, { x: 3 }].reduce( (acumulador, valorAtual) => acumulador + valorAtual.x, valorInicial,);console.log(soma); // retorna 6Redução de um array de arrays
let reduzido = [ [0, 1], [2, 3], [4, 5],].reduce(function (acumulador, valorAtual) { return acumulador.concat(valorAtual);}, []);// reduzido é [0, 1, 2, 3, 4, 5]Utilizando uma arrow function:
let reduzido = [ [0, 1], [2, 3], [4, 5],].reduce((acumulador, valorAtual) => acumulador.concat(valorAtual), []);Contando valores iguais em um objeto
let nomes = ["Alice", "Bob", "Tiff", "Bruce", "Alice"];let quantidadeNomes = nomes.reduce(function (todosNomes, nome) { if (nome in todosNomes) { todosNomes[nome]++; } else { todosNomes[nome] = 1; } return todosNomes;}, {});// quantidade de nomes:// { 'Alice': 2, 'Bob': 1, 'Tiff': 1, 'Bruce': 1 }Agrupando objetos por uma propriedade
let pessoas = [ { nome: "Alice", idade: 21 }, { nome: "Max", idade: 20 }, { nome: "Jane", idade: 20 },];function agruparPor(objetoArray, propriedade) { return objetoArray.reduce(function (acc, obj) { let key = obj[propriedade]; if (!acc[key]) { acc[key] = []; } acc[key].push(obj); return acc; }, {});}let grupodePessoas = agruparPor(pessoas, "idade");// grupodePessoas é:// {// 20: [// { nome: 'Max', idade: 20 },// { nome: 'Jane', idade: 20 }// ],// 21: [{ nome: 'Alice', idade: 21 }]// }Juntando arrays contidos num array de objetos usando o operador spread e ovalorInicial
// friends - um array de objetos// onde o campo "books" é a lista de livros favoritosvar friends = [ { name: "Anna", books: ["Bible", "Harry Potter"], age: 21, }, { name: "Bob", books: ["War and peace", "Romeo and Juliet"], age: 26, }, { name: "Alice", books: ["The Lord of the Rings", "The Shining"], age: 18, },];// allbooks - lista que contém todos os livros de friends +// lista adicional contida em valorInicialvar allbooks = friends.reduce( function (prev, curr) { return [...prev, ...curr.books]; }, ["Alphabet"],);// allbooks = [// 'Alphabet', 'Bible', 'Harry Potter', 'War and peace',// 'Romeo and Juliet', 'The Lord of the Rings',// 'The Shining'// ]Removendo itens duplicados num array
Nota:Se você estiver usando um ambiente compatível comSet andArray.from(), você pode usarlet orderedArray = Array.from(new Set(myArray)) para obter um array em que os itens duplicados tenham sido removidos.
let arr = [1, 2, 1, 2, 3, 5, 4, 5, 3, 4, 4, 4, 4];let result = arr.sort().reduce((init, current) => { if (init.length === 0 || init[init.length - 1] !== current) { init.push(current); } return init;}, []);console.log(result); //[1,2,3,4,5]Substituindo .filter().map() por .reduce()
UsarArray.filter() seguido porArray.map() faz com que o array seja percorrido duas vezes. Você pode obter o mesmo resultado percorrendo o array apenas uma vez comArray.reduce(), o que é, portanto, mais eficiente. (Se você gosta de for loops, você pode usar filter e map percorrendo o array apenas uma vez comArray.forEach()).
const numbers = [-5, 6, 2, 0];const doubledPositiveNumbers = numbers.reduce((accumulator, currentValue) => { if (currentValue > 0) { const doubled = currentValue * 2; accumulator.push(doubled); } return accumulator;}, []);console.log(doubledPositiveNumbers); // [12, 4]Rodando promises em sequência
/** * Roda promises de um promise array de uma maneira encadeada * * @param {array} arr - promise arr * @return {Object} promise object */function runPromiseInSequense(arr) { return arr.reduce((promiseChain, currentPromise) => { return promiseChain.then((chainedResult) => { return currentPromise(chainedResult).then((res) => res); }); }, Promise.resolve());}// promise function 1function p1() { return new Promise((resolve, reject) => { resolve(5); });}// promise function 2function p2(a) { return new Promise((resolve, reject) => { resolve(a * 2); });}// promise function 3function p3(a) { return new Promise((resolve, reject) => { resolve(a * 3); });}const promiseArr = [p1, p2, p3];runPromiseInSequense(promiseArr).then((res) => { console.log(res); // 30});Escrever map usando reduce
if (!Array.prototype.mapUsingReduce) { Array.prototype.mapUsingReduce = function (callback, thisArg) { return this.reduce(function (mappedArray, currentValue, index, array) { mappedArray[index] = callback.call(thisArg, currentValue, index, array); return mappedArray; }, []); };}[1, 2, , 3].mapUsingReduce( (currentValue, index, array) => currentValue + index + array.length,); // [5, 7, , 10]Polyfill
Array.prototype.reduce foi adicionado ao padrão ECMA-262 na quinta edição; e portanto, pode não estar presente em todas as implementações do padrão. Você pode contornar isso inserindo o código a seguir no início de seus scripts, permitindo o uso doreduce() em implementações que não possuem suporte nativo a ele.
// Etapas de produção para o ECMA-262, Edition 5, 15.4.4.21// Referencia: http://es5.github.io/#x15.4.4.21if (!Array.prototype.reduce) { Array.prototype.reduce = function (callback /*, valorInicial*/) { "use strict"; if (this == null) { throw new TypeError( "Array.prototype.reduce chamado é nulo (null) ou indefinido (undefined)", ); } if (typeof callback !== "function") { throw new TypeError(callback + " não é uma função"); } var t = Object(this), len = t.length >>> 0, k = 0, value; if (arguments.length == 2) { value = arguments[1]; } else { while (k < len && !(k in t)) { k++; } if (k >= len) { throw new TypeError( "Reduce possui um array vazio sem um valor inicial", ); } value = t[k++]; } for (; k < len; k++) { if (k in t) { value = callback(value, t[k], k, t); } } return value; };}Especificações
| Specification |
|---|
| ECMAScript® 2026 Language Specification> # sec-array.prototype.reduce> |