Cinco formas interesantes de usar Array.reduce () (y una forma aburrida)

Hola Habr! Le presento la traducción del artículo "Cinco formas interesantes de usar Array.reduce () (y una forma aburrida)" de Chris Ferdinandi.


De todos los métodos modernos de trabajar con matrices, el más difícil de todos que tuve que usar fue Array.reduce ().


A primera vista, parece ser un método simple y aburrido que hace poco. Pero, a pesar de su apariencia modesta, Array.reduce () es una adición poderosa y flexible a su conjunto de herramientas de desarrollador.


Hoy, veamos algunas cosas interesantes que puedes hacer con Array.reduce ().


Cómo funciona Array.reduce ()


La mayoría de los métodos de matriz modernos devuelven una nueva matriz. El método Array.reduce () es un poco más flexible. Él puede devolver cualquier cosa. Su propósito es tomar una matriz y comprimir su contenido en un valor.


Este valor puede ser un número, una cadena o incluso un objeto o una nueva matriz. Esta es la parte que siempre me desconcertó: ¡no entendí lo flexible que es!


Sintaxis


Array.reduce () toma dos argumentos: el método de devolución de llamada, que se ejecuta para iniciar cada elemento en la matriz, y el valor inicial initialValue.


La devolución de llamada también toma dos argumentos: el acumulador, que es el valor combinado actual, y el elemento actual en el bucle currentValue. Todo lo que devuelva se usa como acumulador para el siguiente elemento del bucle. El primer bucle utiliza el valor inicial en su lugar.


var myNewArray = [].reduce(function (accumulator, current) { return accumulator;}, starting); }, starting); 

Veamos algunos ejemplos.


 var myNewArray = [].reduce(function (accumulator, current) { return accumulator;}, starting); 

1. Suma de números


Suponga que tiene una serie de números que desea sumar. Usando Array.forEach (), podemos hacer algo como esto:


 var total = 0; [1, 2, 3].forEach(function (num) { total += num; }); 

Este es un ejemplo cliché para usar Array.reduce (). La palabra "acumulador" es confusa, por lo que en este ejemplo la llamaremos "suma" porque es lo que es inherentemente.


 var total = [1, 2, 3].reduce(function (sum, current) { return sum + current; }, 0);    0    . 

En la devolución de llamada, agregamos el valor actual a la cantidad que tiene un valor inicial de 0 en el primer ciclo, luego 1 (valor inicial 0 más valor de elemento 1), luego 3 (valor total 1 más valor de elemento 2) y así sucesivamente.
Un ejemplo


2.Una alternativa a la combinación de los métodos de matriz Array.map () y Array.filter () en un solo paso


Imagina que hay muchos magos en Hogwarts.


 var wizards = [ { name: 'Harry Potter', house: 'Gryfindor' }, { name: 'Cedric Diggory', house: 'Hufflepuff' }, { name: 'Tonks', house: 'Hufflepuff' }, { name: 'Ronald Weasley', house: 'Gryfindor' }, { name: 'Hermione Granger', house: 'Gryfindor' }]; 

Queremos crear una nueva matriz que contendrá solo los nombres de los maestros de Hufflepuff. Una forma de hacerlo es utilizar el método Array.filter () para recuperar solo aquellos asistentes que tienen una propiedad Hufflepuff en casa. Luego usamos el método Array.map () para crear una nueva matriz que contenga solo la propiedad de nombre para los maestros restantes.


 //      var hufflepuff = wizards.filter(function (wizard) { return wizard.house === 'Hufflepuff'; }).map(function (wizard) { return wizard.name; }); 

Usando el método Array.reduce (), puede obtener la misma matriz en una sola pasada, lo que mejorará nuestro rendimiento. Pasamos una matriz vacía ([]) como valor inicial. En cada pase, verificamos si wizard.house es un Hufflepuff. Si es así, envíelo a newArr (nuestro acumulador en este ejemplo). Si no, no hagas nada.


En cualquier caso, devuelva newArr para obtener el acumulador en la próxima pasada.


 //      var hufflepuff = wizards.reduce(function (newArr, wizard) { if (wizard.house === 'Hufflepuff') { newArr.push(wizard.name); } return newArr; }, []); 

Un ejemplo


3.Crear marcado desde una matriz


¿Qué sucede si, en lugar de crear una matriz de nombres, queremos crear una lista desordenada de maestros en Hufflepuff? En lugar de una matriz vacía en Array.reduce () como nuestro valor inicial, pase una cadena vacía ('') y llámela html.


Si wizard.house es igual a Hufflepuff, combinamos nuestra cadena html con wizard.name envuelta en los elementos de la lista de apertura y cierre (li). Luego devuelva HTML como acumulador en el siguiente ciclo.


 //      var hufflepuffList = wizards.reduce(function (html, wizard) { if (wizard.house === 'Hufflepuff') { html += '<li>' + wizard.name + '</li>'; } return html; }, ''); 

Agregue el elemento de lista desordenada de apertura y cierre antes y después de Array.reduce (). Ahora está listo para agregar marcado al DOM.


 //      var hufflepuffList = '<ul>' + wizards.reduce(function (html, wizard) { if (wizard.house === 'Hufflepuff') { html += '<li>' + wizard.name + '</li>'; } return html; }, '') + '</ul>'; 

Un ejemplo


4. Agrupando elementos similares en una matriz


La biblioteca lodash tiene un método groupBy () que toma una colección de elementos como una matriz y los agrupa en un objeto según algunos criterios.


Digamos que necesitamos una matriz de números.


Si queremos agrupar todos los elementos en números por su valor entero, entonces esto debe hacerse usando lodash.


 var numbers = [6.1, 4.2, 6.3]; // returns {'4': [4.2], '6': [6.1, 6.3]} _.groupBy(numbers, Math.floor); 

Si hay una variedad de palabras, y necesita agrupar los elementos en las palabras por su longitud, lo haremos.


 var words = ['one', 'two', 'three']; // returns {'3': ['one', 'two'], '5': ['three']} _.groupBy(words, 'length'); 

Crear una función groupBy () usando Array.reduce ()


Puede recrear la misma funcionalidad utilizando el método Array.reduce ().


Creamos una función auxiliar groupBy (), que toma una matriz y criterios para ordenar como argumentos. Dentro de groupBy (), ejecutaremos Array.reduce () para nuestra matriz, pasando un objeto vacío ({}) como punto de partida y devolviendo el resultado.


 var groupBy = function (arr, criteria) { return arr.reduce(function (obj, item) { // Some code will go here... }, {}); }; 

Dentro de Array.reduce (), llamamos a la función de devolución de llamada para verificar si el criterio es una función aplicada a un elemento o una propiedad de un elemento. Luego obtenemos su valor del elemento actual.


Si el objeto aún no tiene una propiedad con este valor, créelo [propiedad] y asigne una matriz vacía como su valor. Finalmente, agregue un elemento a esta propiedad y devuelva el objeto como acumulador para el próximo ciclo.


 var groupBy = function (arr, criteria) { return arr.reduce(function (obj, item) { //   ,        //  var key = typeof criteria === 'function' ? criteria(item) : item[criteria]; //    ,  . if (!obj.hasOwnProperty(key)) { obj[key] = []; } //     obj[key].push(item); //      return obj; }, {});}; 

Demostración de una función auxiliar completa.


Un agradecimiento especial a Tom Bremer por su ayuda. Esta función auxiliar y mucho más se pueden encontrar en Vanilla JS Toolkit .


5. Combinando datos de dos fuentes en una matriz


Recordemos nuestra lista de magos.


 var wizards = [ { name: 'Harry Potter', house: 'Gryfindor' }, { name: 'Cedric Diggory', house: 'Hufflepuff' }, { name: 'Tonks', house: 'Hufflepuff' }, { name: 'Ronald Weasley', house: 'Gryfindor' }, { name: 'Hermione Granger', house: 'Gryfindor' }]; 

¿Qué pasaría si hubiera un conjunto de datos diferente: un objeto con una casa y puntos ganados por cada mago?


 var points = { HarryPotter: 500, CedricDiggory: 750, RonaldWeasley: 100, HermioneGranger: 1270 }; 

Imagine que queremos combinar ambos conjuntos de datos en una matriz con el número de puntos agregados a los datos de cada asistente en la matriz de asistentes. Como hacerlo


¡El método Array.reduce () es perfecto para esto!


 var wizardsWithPoints = wizards.reduce(function (arr, wizard) { //     points,     // var key = wizard.name.replace(' ', ' '); //     ,  , //   0. if (points[key]) { wizard.points = points[key]; } else { wizard.points = 0; } //   wizard   . arr.push(wizard); //  . return arr; }, []); 

Un ejemplo de combinación de datos de dos fuentes en una matriz .


6. Combinando datos de dos fuentes en un objeto


¿Qué sucede si en cambio es necesario combinar las dos fuentes de datos en un objeto en el que el nombre de cada asistente es la clave, y su casa y sus anteojos son propiedades? Nuevamente, el método Array.reduce () es perfecto para esto.


 var wizardsAsAnObject = wizards.reduce(function (obj, wizard) { //      points,     // var key = wizard.name.replace(' ', ' '); //     ,  , //   0. if (points[key]) { wizard.points = points[key]; } else { wizard.points = 0; } //   name delete wizard.name; //   wizard    obj[key] = wizard; //   return obj; }, {}); 

Un ejemplo de combinación de datos de dos fuentes en un objeto .


¿Debo usar Array.reduce ()?


El método Array.reduce () ha evolucionado de sin sentido a mi método JavaScript favorito. Entonces, ¿vale la pena usarlo? Y cuando


El método Array.reduce () tiene un fantástico soporte para el navegador. Funciona en todos los navegadores modernos y en IE9. Hace tiempo que es compatible con navegadores móviles. Si necesita aún más, puede agregar un polyfill para devolver el soporte en IE6.


El problema más grave puede ser que Array.reduce () es confuso para las personas que nunca antes lo han encontrado [método]. La combinación de los métodos Array.filter () con Array.map () es más lenta e implica pasos adicionales, pero es más fácil de leer. Los nombres de los métodos muestran lo que deben hacer.


Como ya se mencionó, el método Array.reduce (), en general, simplifica las cosas más complejas. Un buen ejemplo es la función auxiliar groupBy ().


En última instancia, esta es otra herramienta para su kit de herramientas. Una herramienta que, si se usa correctamente, puede dar superpoderes.


Sobre el autor


Chris Ferdinandi ayuda a las personas a aprender JavaScript vainilla. Él cree que hay una manera más simple y confiable de hacer cosas por Internet.


Chris es el autor de la serie Vanilla JS Pocket Guide , creador del currículum Vanilla JS Academy y presentador del Vanilla JS Podcast . Miles de desarrolladores leen su boletín informativo para desarrolladores todos los días de la semana.


Entrenó a desarrolladores en organizaciones como Chobani y Boston Globe, y Apple y Harvard Business School utilizaron sus complementos de JavaScript. Chris Coyer, fundador de CSS-Tricks y CodePen, describió su trabajo como "interminablemente citado".


A Chris le encantan los piratas, los cachorros y las películas de Pixar, y también vive cerca de granjas de caballos en el campo de Massachusetts. Él dirige Go Make Things con un cachorro Bailey.

Source: https://habr.com/ru/post/483182/


All Articles