Last Updated:
Photo by Pankaj Patel on Unsplash

Métodos de iteración sobre arrays en Javascript

javascript

Table of Contents

Los clásicos ciclos for y while no son la única manera de recorrer los elementos de un array en Javascript.

Existen una serie de métodos en los arrays que nos permiten iterar sobre cada uno de los  elementos de estos de forma sencilla, ahorrándonos mucho trabajo y simplificando nuestro código. Aprenderlos te va ha hacer un desarrollador mucho más productivo.

Estos métodos hacen parte de las llamadas funciones de orden superior (funciones que toman otra función como argumento o que retornan una función) y hacen parte de la programación funcional de Javascript.

Digamos que tenemos una lista de números y queremos crear otra lista con cada uno de los elementos multiplicado por dos. Una solución clásica sería crear una función con un ciclo for que itere sobre cada uno de los elementos multiplicando cada uno de ellos por dos y devuelva la lista de esos elementos. Sería algo así:

const array = [2, 4, 6, 8];

function multiplicarPorDos (lista) {
  let array2 = [];	

  for (let i = 0; i < lista.length; i++) {
    array2.push(lista[i] * 2);
  }
  return array2;
}

const doble = multiplicarPorDos(array);
console.log(doble);
// esto daría [4, 8, 12, 16];

Sin embargo, con los métodos de iteración sobre arrays que trae Javascript de fábrica, podemos ese mismo tipo de cosas con muchas menos líneas de código y de forma más legible como te voy a mostrar a continuación.

map()

El método map() toma como argumentos una función anónima y retorna un nuevo array con los resultados de aplicar esta función una vez sobre cada uno de los elementos del array original. Esta función anónima toma como su primer argumento el elemento sobre el cual estemos iterando (puede tomar dos argumentos más opcionalmente).

Veamos cómo podemos refactorizar el código anterior usando este método.

const array = [2, 4, 6, 8];

const doble = array.map((elemento) => {
  return elemento * 2;
});

console.log(doble); // [4, 8, 12, 16];

forEach()

Este método también ejecuta la función que recibe como argumento una vez por cada uno de los elementos del array. A diferencia de map(), no modifica el array original.

La función callback (así se le llama a la función que reciben estos métodos), recibe como argumentos el valor del elemento sobre el cuál se está iterando y otros dos más que no son obligatorios.

Si quisiéramos obtener un nuevo array con cada uno de sus elementos multiplicado por dos, tendríamos que crear uno vacío y agregar los nuevos elementos multiplicados por dos de forma similar a como hicimos al principio con el ciclo for.

const array = [2, 4, 6, 8];
let doble = [];

array.forEach((elemento) => {
  doble.push(elemento * 2);
});

console.log(doble); // [4, 8, 12, 16];

find()

Retorna el primer elemento del array que satisface el criterio de la función callback que se le pase. Si no encuentra ningún elemento que cumpla dicho criterio, retorna undefined.

En el siguiente fragmento de código vamos a iterar sobre el array inventario y vamos a encontrar el elemento cuya propiedad cantidad sea igual a 5 (que sería "lapiceros")

const inventario = [
  {elemento: "libros", cantidad: 2},
  {elemento: "lapiceros", cantidad: 5},
  {elemento: "borradores", cantidad: 3}
];

const elementoEncontrado = inventario.find((e) => {
  return e.cantidad === 5;
});

console.log(elementoEncontrado); 
// imprime en pantalla {elemento: "lapiceros", cantidad: 5}

filter()

Este método recorre cada uno de los elementos del array evaluando si cada uno de ellos cumple con el criterio de la función que recibe de argumento. Si es así, retorna un nuevo array con estos elementos que pasan al prueba sin modificar el original.

En este ejemplo vamos a filtrar los elementos cuya cantidad es impar del array inventario

const inventario = [
  {elemento: "libros", cantidad: 2},
  {elemento: "lapiceros", cantidad: 5},
  {elemento: "borradores", cantidad: 3}
];

const elementosImpares = inventario.filter((cosa) => {
  return cosa.cantidad % 2 !== 0;
});

console.log(elementosFiltrados);
// imprime [{elemento: "lapiceros", cantidad: 5},
// 	    {elemento: "borradores", cantidad: 3}];

sort()

Como su nombre lo indica, sort() sirve para ordenar los elementos de un array. Por defecto, el orden de los elementos es ascendente y de acuerdo con valor Unicode de los elementos (o lo que es lo mismo, al valor que tendrían al convertirse al tipo string). Este método modifica el array original.

En caso de que queramos ordenar un array de números, por ejemplo, debemos pasar un callback con dos argumetos a y b así:

const numeros = [4, 2, 5, 1, 3];

numeros.sort((a, b) => {
  return a - b;
});

console.log(numeros); // [1, 2, 3, 4, 5]

Un ejemplo más complejo de sort()

Ahora digamos que queremos ordenar un array de objetos de acuerdo con una de sus propiedades que es de tipo string. En este caso debemos pasar un callback también con dos valores (a y b) y hacer una comparación entre estos dos.

  • Si a < b retornamos  -1
  • Si a > b retornamos 1
  • Si no se cumple ninguna de las anteriores, retornamos 0
const inventario = [
  {elemento: "libros", cantidad: 2},
  {elemento: "lapiceros", cantidad: 5},
  {elemento: "borradores", cantidad: 3}
];

inventario.sort((a, b) => {
  if (a.elemento > b.elemento) {
    return 1;
  }
  if (a.elemento < b.elemento) {
    return -1;
  }
  return 0;
});

Esto ordenaría el array inventario de acuerdo a la propiedad elemento en orden alfabético.

some()

Si lo que queremos es comprobar si un elemento del array cumple con cierta condición, podemos pasarle un callback al método some() que recibe como primer argumento el elemento sobre el que se iterando (opcionalmente puede recibir hasta tres argumentos más) y retorna true si alguno de los elementos cumple con la condición. En caso contrario retorna false.

Aquí vamos a evaluar si en el array numeros se cumplen dos condiciones:

  • hay elementos mayores a 4
  • hay elementos mayores a 6
const numeros = [4, 2, 5, 1, 3];

const hayMayoresA4 = numeros.some((numero) => {
  return  numero > 4;
});

const hayMayoresA6 = numeros.some((numero) => {
  return  numero > 6;
});

console.log(hayMayoresA4, hayMayoresA6);
// true false

Otro método parecido a este es every(), que retorna true si todos los elementos cumplen la condición y false en caso contrario.

reduce()

Finalmente llegamos al último método del que voy a hablar en este artículo.

Este método recibe como argumentos un callback y un valor inicial que es opcional. Si no se provee un valor inicial, el valor por defecto de este será el primer elemento del array. El callback a su vez recibe dos argumentos: uno para el acumulador y otro para el valor actual sobre el que se esté iterando (dos argumentos más se pueden proveer, pero son opcionales).

Lo que hace este método es reducir el array a un único valor de acuerdo a la aplicación algoritmo de la función callback sobre cada uno de los elementos del array. Vamos a ilustrarlo con un ejemplo sencillo:

const numeros = [4, 2, 5, 1, 3];

const suma = numeros.reduce((acumulador, valorActual) => {
  return acumulador + valorActual;
});

console.log(suma); // 15

Aquí sumamos todos los elementos de numeros y guardamos el resultado en la variable suma.

Como no pasamos un valor inicial, acumulador tomó el valor del primer elemento del array (4). Luego sumamos acumulador con valorActual (que es el elemento  sobre el que está actuando el callback en cada iteración). El resultado se asigna a acumulador y se procede a hacer la suma de este con el siguiente elemento en el array, que sería el valor 2. Así sucesivamente se van sumando los elementos en el array y guardando el valor de esta suma en acumulador, que se retorna al final una vez se haya ejecutado el callback en todos los elementos del array.

Usando reduce() como map()

En resumen, reduce() nos sirve para hacer lo mismo que podríamos hacer map() o con los otros métodos que retornan arrays al pasarles una función. En el siguiente fragmento de código puedes ver un ejemplo de eso:

const inventario = [
  {elemento: "libros", cantidad: 2},
  {elemento: "lapiceros", cantidad: 5},
  {elemento: "borradores", cantidad: 3}
];

// vamos a sacar todos los inventario.elemento en un solo array

let elementos = inventario.reduce((acumulador, actual) => {
  acumulador.push(actual.elemento);
  return acumulador;	
}, []); // pasamos un array vacío como segundo argumento

console.log(elementos)
// ["libros", "lapiceros", "borradores"]

Como puedes ver, estos métodos de iteración son bastante útiles y te ayudan a simplificar el código y ahorrar trabajo. Si vas a programar en React, dominar su uso te va a resultar especialmente útil, porque se usan bastante en esa libría.

Sin embargo el verdadero poder de estos métodos está en que se pueden componer unos con otros encadenándolos entre sí.

Componiendo métodos de iteración

En este ejemplo vamos a crear un nuevo array nuevosNumeros a partir de tomar numeros, filtrar los elementos mayores a 2, multiplicarlos por 3 y finalmente ordenarlos de menor a mayor:

const numeros = [4, 2, 5, 1, 3];

let nuevosNumeros =
  numeros
    .filter(numero => numero > 2)
    .map(numero => numero * 3)
    .sort((a, b) => a - b);

console.log(nuevosNumeros)
// [9, 12, 15]// [9, 12, 15]

Nota que aquí simplificamos las arrow functions eliminando el return y las llaves { } que suelen encerrar el código de la función.

Estos son los métodos más comunes de iteración sobre arrays en Javascript que deberías conocer y dominar a la perfección.

Para una completa descripción de todos los métodos y su utilización, además de detalles sobre su eficiencia, puedes visitar la documentación de Mozilla.org o también la documentación de w3schools (en inglés).

Comments