diff options
author | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
---|---|---|
committer | Peter Bengtsson <mail@peterbe.com> | 2020-12-08 14:42:52 -0500 |
commit | 074785cea106179cb3305637055ab0a009ca74f2 (patch) | |
tree | e6ae371cccd642aa2b67f39752a2cdf1fd4eb040 /files/pt-br/web/javascript/reference/global_objects/array/reduce | |
parent | da78a9e329e272dedb2400b79a3bdeebff387d47 (diff) | |
download | translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.gz translated-content-074785cea106179cb3305637055ab0a009ca74f2.tar.bz2 translated-content-074785cea106179cb3305637055ab0a009ca74f2.zip |
initial commit
Diffstat (limited to 'files/pt-br/web/javascript/reference/global_objects/array/reduce')
-rw-r--r-- | files/pt-br/web/javascript/reference/global_objects/array/reduce/index.html | 513 |
1 files changed, 513 insertions, 0 deletions
diff --git a/files/pt-br/web/javascript/reference/global_objects/array/reduce/index.html b/files/pt-br/web/javascript/reference/global_objects/array/reduce/index.html new file mode 100644 index 0000000000..0268b64c00 --- /dev/null +++ b/files/pt-br/web/javascript/reference/global_objects/array/reduce/index.html @@ -0,0 +1,513 @@ +--- +title: Array.prototype.reduce() +slug: Web/JavaScript/Reference/Global_Objects/Array/Reduce +tags: + - Array + - JavaScript + - Métodos + - Prototipo + - Referencia + - reduce() +translation_of: Web/JavaScript/Reference/Global_Objects/Array/Reduce +--- +<div>{{JSRef}}</div> + +<p>O método <code><strong>reduce()</strong></code> executa uma função <strong>reducer</strong> (fornecida por você) para cada elemento do array, resultando num único valor de retorno.</p> + +<div>{{EmbedInteractiveExample("pages/js/array-reduce.html")}}</div> + +<p class="hidden">A fonte desse exemplo interativo está armazenada em um repositório do GitHub. Se você quiser contribuir com o projeto de exemplos interativos, clone https://github.com/mdn/interactive-examples e envie-nos um pull request.</p> + +<p>A função <strong>reducer</strong> recebe quatro parâmetros:</p> + +<ol> + <li>Acumulador (<code>acc</code>)</li> + <li>Valor Atual (<code>cur</code>)</li> + <li>Index Atual (<code>idx</code>)</li> + <li>Array original (<code>src</code>)</li> +</ol> + +<p>O valor de retorno da sua função <strong>reducer</strong> é 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.</p> + +<h2 id="Syntax" name="Syntax">Sintaxe</h2> + +<pre class="brush: js notranslate"><code><var>array</var>.reduce(<var>callback( acumulador, valorAtual</var>[, index[, array]] )[, <var>valorInicial</var>]))</code></pre> + +<h3 id="Parâmetros">Parâmetros</h3> + +<dl> + <dt><code>callback</code></dt> + <dd>Função que é executada em cada valor no array (exceto no primeiro, se nenhum <font face="Consolas, Liberation Mono, Courier, monospace"><code>valorInicial</code></font> for passado); recebe quatro argumentos:</dd> +</dl> + +<p><strong><font face="Consolas, Liberation Mono, Courier, monospace"><code>acumulador</code></font></strong></p> + +<p>Opcional. O índice do elemento atual que está sendo processado no array. Começa a partir do index <code>0</code> se um <font face="Consolas, Liberation Mono, Courier, monospace"><code>valorInicial</code> </font>for fornecido. Do contrário, começa do index <code>1</code>.</p> + +<dl> + <dt><code>valorInicial</code></dt> + <dd>Opcional. Valor a ser usado como o primeiro argumento da primeira chamada da função <code>callback</code>. Se nenhum <code>valorInicial</code> é fornecido, o primeiro elemento do array será usado como o valor inicial do <font face="Consolas, Liberation Mono, Courier, monospace"><code>acumulador</code></font> e o <code>valorAtual</code> não será lido. Chamar <code>reduce()</code> em uma array vazia sem valor inicial retornará um erro.</dd> +</dl> + +<h3 id="Valor_retornado">Valor retornado</h3> + +<p>O valor que resulta da redução.</p> + +<h2 id="Description" name="Description">Descrição</h2> + +<p>O método <code>reduce()</code> executa a função de <code>callback</code> uma vez para cada elemento presente no array, excluindo furos (valores indefinidos), recebendo quatro argumentos:</p> + +<ol> + <li><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);"><em>acumulador</em></span></font> - valor inicial (ou o valor do callback anterior),</li> + <li><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);"><em>valorAtual</em></span></font> - o valor do elemento atual</li> + <li><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);"><em>index</em></span></font> - o índice atual e</li> + <li><code><var>array</var></code> - o array onde a iteração está ocorrendo.</li> +</ol> + +<p>A primeira vez que o callback é chamado, o<font face="Consolas, Liberation Mono, Courier, monospace"> <code>acumulador</code> e o <code>valorAtual</code> </font>podem ter um de dois valores possíveis<font face="Consolas, Liberation Mono, Courier, monospace">. </font>Se o <code><font face="Consolas, Liberation Mono, Courier, monospace">valorInicial</font></code><font face="Consolas, Liberation Mono, Courier, monospace"> </font>tiver<font face="Consolas, Liberation Mono, Courier, monospace"> </font>sido fornecido na chamada à função <font face="Consolas, Liberation Mono, Courier, monospace"><code>reduce()</code></font>, então o <font face="Consolas, Liberation Mono, Courier, monospace"><code>acumulador</code></font> será igual ao <code>valorInicial</code> e o <font face="consolas, Liberation Mono, courier, monospace"><code>valorAtual</code> </font>será igual ao primeiro valor no array. Caso nenhum <code>valorInicial</code> seja fornecido, <font face="Consolas, Liberation Mono, Courier, monospace"><code>acumulador</code></font> será igual ao primeiro valor no array, e <code>valorAtual</code> será igual ao segundo.</p> + +<div class="note"> +<p><strong>Nota</strong>: Se o <code>valorInicial</code> não tiver sido passado como argumento, então <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">reduce()</span></font> executará o callback da função começando a partir do índice 1 (<font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">index 1</span></font>), pulando o primeiro índice (<code>index 0</code>). Se o <code>valorInicial</code> for passado como argumento, a função irá começar no <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">index 0</span></font>.</p> +</div> + +<p>Se a array estiver vazia e o <code>valorInicial</code> não tiver sido informado, uma exceção do tipo {{jsxref("Global_Objects/TypeError", "TypeError")}} será lançada.</p> + +<p>Se a array possuir somente um elemento (independente da posição) e o <code>valorInicial</code> não tiver sido fornecido, ou se <code>valorInicial</code> for fornecido, mas a array estiver vazia, o valor será retornado sem que a função de <code>callback</code> seja chamada.</p> + +<p>É mais seguro provir um <code>valorInicial</code>, porque existem até <em>quatro</em> possíveis saídas sem o <code>valorInicial</code>, como mostrado no exemplo:</p> + +<pre class="brush: js notranslate">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 );</pre> + +<h3 id="Como_funciona_o_reduce">Como funciona o reduce()</h3> + +<p>Suponha que o seguinte uso de <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">reduce()</span></font> tenha ocorrido:</p> + +<pre class="brush: js notranslate">[0, 1, 2, 3, 4].reduce(function(a<font face="Consolas, Liberation Mono, Courier, monospace"><code>cumulador</code></font>, valorAtual, index, array) { + return a<font face="Consolas, Liberation Mono, Courier, monospace"><code>cumulador</code></font> + valorAtual; +}); +// 10</pre> + +<p>O callback será invocado quatro vezes, com os argumentos e valores em cada chamada sendo:</p> + +<table style="width: 100%;"> + <thead> + <tr> + <th scope="col"></th> + <th scope="col"><font face="Consolas, Liberation Mono, Courier, monospace"><code>acumulador</code></font></th> + <th scope="col"><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">valorAtual</span></font></th> + <th scope="col"><font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">index</span></font></th> + <th scope="col"><code>array</code></th> + <th scope="col"><strong>valor de retorno</strong></th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">primeira chamada</th> + <td><code>0</code></td> + <td><code>1</code></td> + <td><code>1</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>1</code></td> + </tr> + <tr> + <th scope="row">segunda chamada</th> + <td><code>1</code></td> + <td><code>2</code></td> + <td><code>2</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>3</code></td> + </tr> + <tr> + <th scope="row">terceira chamada</th> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>6</code></td> + </tr> + <tr> + <th scope="row">quarta chamada</th> + <td><code>6</code></td> + <td><code>4</code></td> + <td><code>4</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>10</code></td> + </tr> + </tbody> +</table> + +<p>O valor retornado pelo <code>reduce</code> será o da última chamada à callback <code>(10)</code>.</p> + +<p>Você também pode usar uma {{jsxref("Functions/Arrow_functions", "Arrow Function","",1)}} em vez de uma função completa. O código abaixo produz a mesma saída que o código do bloco acima:</p> + +<pre class="brush: js line-numbers language-js notranslate">[0, 1, 2, 3, 4].reduce( (accum, curr) => accum + curr );</pre> + +<p>Se você informar um <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">valorInicial</span></font> como o segundo argumento de reduce, o resultado será:</p> + +<pre class="brush: js notranslate">[0, 1, 2, 3, 4].reduce(function(acumulador, valorAtual, indice, array) { + return acumulador + valorAtual; +}, 10); + +// 20</pre> + +<table style="width: 100%;"> + <thead> + <tr> + <th scope="col"><code>callback</code></th> + <th scope="col"><font face="Consolas, Liberation Mono, Courier, monospace"><code>acumulador</code></font></th> + <th scope="col"><code>valorAtual</code></th> + <th scope="col"><code>index</code></th> + <th scope="col"><code>array</code></th> + <th scope="col"><code>valor de retorno</code></th> + </tr> + </thead> + <tbody> + <tr> + <th scope="row">primeira chamada</th> + <td><code>10</code></td> + <td><code>0</code></td> + <td><code>0</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>10</code></td> + </tr> + <tr> + <th scope="row">segunda chamada</th> + <td><code>10</code></td> + <td><code>1</code></td> + <td><code>1</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>11</code></td> + </tr> + <tr> + <th scope="row">terceira chamada</th> + <td><code>11</code></td> + <td><code>2</code></td> + <td><code>2</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>13</code></td> + </tr> + <tr> + <th scope="row">quarta chamada</th> + <td><code>13</code></td> + <td><code>3</code></td> + <td><code>3</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>16</code></td> + </tr> + <tr> + <th scope="row">quinta chamada</th> + <td><code>16</code></td> + <td><code>4</code></td> + <td><code>4</code></td> + <td><code>[0, 1, 2, 3, 4]</code></td> + <td><code>20</code></td> + </tr> + </tbody> +</table> + +<p>O retorno da última chamada <code>20</code>,é retornado como resultado da função <code>reduce()</code>.</p> + +<h2 id="Examples" name="Examples">Exemplos</h2> + +<h3 id="Example_Sum_up_all_values_within_an_array" name="Example:_Sum_up_all_values_within_an_array">Soma todos os valores de uma array</h3> + +<pre class="brush: js notranslate">let total = [0, 1, 2, 3].reduce(function(acumulador, valorAtual) { + return acumulador + valorAtual; + }, 0) +// retorna 6</pre> + +<p>outra alternativa é usar uma arrow function:</p> + +<pre class="notranslate"><code>var total = [ 0, 1, 2, 3 ].reduce( + ( acumulador, valorAtual ) => acumulador + valorAtual, + 0 +);</code></pre> + +<h3 id="Soma_de_valores_de_um_objeto_de_um_array">Soma de valores de um objeto de um array</h3> + +<p>Para resumir os valores contidos em um array, você <strong>deve </strong>fornecer um <font face="consolas, Liberation Mono, courier, monospace"><span style="background-color: rgba(220, 220, 220, 0.5);">valorInicial</span></font>, para que cada item passe por sua função.</p> + +<pre class="notranslate"><code>var valorInicial = 0; +var soma = [{x: 1}, {x: 2}, {x: 3}].reduce(function (acumulador, valorAtual) { + return acumulador + valorAtual.x; +}, valorInicial) + +console.log(soma) // retorna 6</code></pre> + +<p>Utilizando uma arrow function:</p> + +<pre class="notranslate"><code>var valorInicial = 0; +var soma = [{x: 1}, {x: 2}, {x: 3}].reduce( + (acumulador , valorAtual) => acumulador + valorAtual.x + , valorInicial +); + +console.log(soma) // retorna 6</code> +</pre> + +<h3 id="Example_Flatten_an_array_of_arrays" name="Example:_Flatten_an_array_of_arrays">Redução de um array de arrays</h3> + +<pre class="notranslate">let reduzido = [[0, 1], [2, 3], [4, 5]].reduce( + function(acumulador, valorAtual) { + return acumulador.concat(valorAtual) + }, + [] +) +// reduzido é [0, 1, 2, 3, 4, 5]</pre> + +<p>Utilizando uma arrow function:</p> + +<pre class="notranslate"><code>let reduzido = [[0, 1], [2, 3], [4, 5]].reduce( + ( acumulador, valorAtual ) => acumulador.concat(valorAtual), + [] +);</code></pre> + +<h3 id="Contando_valores_iguais_em_um_objeto">Contando valores iguais em um objeto</h3> + +<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">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 }</code> +</pre> + +<h3 id="Agrupando_objetos_por_uma_propriedade">Agrupando objetos por uma propriedade</h3> + +<pre class="notranslate"><code>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 }] +// }</code></pre> + +<h3 id="Juntando_arrays_contidos_num_array_de_objetos_usando_o_operador_spread_e_o_valorInicial">Juntando arrays contidos num array de objetos usando o operador spread e o <code>valorInicial</code></h3> + +<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">// friends - um array de objetos +// onde o campo "books" é a lista de livros favoritos +var 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 valorInicial +var 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' +// ]</code></pre> + +<h3 id="Removendo_itens_duplicados_num_array">Removendo itens duplicados num array</h3> + +<div class="blockIndicator note"> +<p><strong>Nota:</strong> Se você estiver usando um ambiente compatível com {{jsxref("Set")}} and {{jsxref("Array.from()")}}, você pode usar <code>let orderedArray = Array.from(new Set(myArray))</code> para obter um array em que os itens duplicados tenham sido removidos.</p> +</div> + +<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">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]</code> +</pre> + +<h3 id="Substituindo_.filter.map_por_.reduce">Substituindo .filter().map() por .reduce()</h3> + +<p>Usar {{jsxref("Array.filter()")}} seguido por {{jsxref("Array.map()")}} faz com que o array seja percorrido duas vezes. Você pode obter o mesmo resultado percorrendo o array apenas uma vez com {{jsxref("Array.reduce()")}}, o que é, portanto, mais eficiente. (Se você gosta de for loops, você pode usar filter e map percorrendo o array apenas uma vez com {{jsxref("Array.forEach()")}}).</p> + +<pre class="notranslate">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]</pre> + +<h3 id="Rodando_promises_em_sequência">Rodando promises em sequência</h3> + +<pre class="brush: js line-numbers language-js notranslate"><code class="language-js">/** + * 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 1 +function p1() { + return new Promise((resolve, reject) => { + resolve(5); + }); +} + +// promise function 2 +function p2(a) { + return new Promise((resolve, reject) => { + resolve(a * 2); + }); +} + +// promise function 3 +function p3(a) { + return new Promise((resolve, reject) => { + resolve(a * 3); + }); +} + +const promiseArr = [p1, p2, p3]; +runPromiseInSequense(promiseArr) + .then((res) => { + console.log(res); // 30 + });</code></pre> + +<h3 id="Escrever_map_usando_reduce">Escrever map usando reduce</h3> + +<pre class="notranslate">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]</pre> + +<h2 id="Polyfill" name="Polyfill">Polyfill</h2> + +<p><code>Array.prototype.reduce</code> 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 do <code>reduce()</code> em implementações que não possuem suporte nativo a ele.</p> + +<pre class="brush: js notranslate">// Etapas de produção para o ECMA-262, Edition 5, 15.4.4.21 +// Referencia: http://es5.github.io/#x15.4.4.21 +if (!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; + }; +} +</pre> + +<h2 id="Specifications" name="Specifications">Especificações</h2> + +<table class="standard-table"> + <tbody> + <tr> + <th scope="col">Especificação</th> + <th scope="col">Status</th> + <th scope="col">Comentário</th> + </tr> + <tr> + <td>{{SpecName('ES5.1', '#sec-15.4.4.21', 'Array.prototype.reduce')}}</td> + <td>{{Spec2('ES5.1')}}</td> + <td> + <p>Definição inicial. Implemetada no JavaScript 1.8.</p> + </td> + </tr> + <tr> + <td>{{SpecName('ES6', '#sec-array.prototype.reduce', 'Array.prototype.reduce')}}</td> + <td>{{Spec2('ES6')}}</td> + <td></td> + </tr> + </tbody> +</table> + +<h2 id="Browser_compatibility" name="Browser_compatibility">Navegadores compatíveis</h2> + +<p>A tabela de compatibilidade encontrada nesta página é gerada a partir de dados estruturados. Se você deseja contribuir com os dados, consulte : <a href="https://github.com/mdn/browser-compat-data">https://github.com/mdn/browser-compat-data</a> e envie-nos um "pull request".</p> + +<div>{{Compat("javascript.builtins.Array.reduce")}}</div> + +<h2 id="See_also" name="See_also">Leia também</h2> + +<ul> + <li>{{jsxref("Array.prototype.reduceRight()")}}</li> +</ul> |