Original article: https://www.freecodecamp.org/news/nesting-for-loops-in-javascript/

Si tienes problemas para entender el desafío Anida bucles "for" de freeCodeCamp, no te preocupes. Te cubrimos las espaldas.

En este problema tienes que completar la función multiplyAll(), y toma un arreglo multidimensional como argumento. Recuerda que un arreglo multidimensional, a veces llamado arreglo 2D, no es más que un arreglo de arreglos, por ejemplo, [[1,2], [3,4], [5,6]].

En el editor de la derecha, multiplyAll() se define como sigue:

function multiplyAll(arr) {
  var product = 1;
  // Sólo cambie el código inferior a esta línea

  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

Tienes que completar la función para que multiplique la variable product por cada número de los sub arreglos del parámetro arr, que es un arreglo multidimensional.

Hay muchas formas diferentes de resolver este problema, pero nos centraremos en el método más sencillo utilizando bucles for.

Configura tus bucles for

Como arr es un arreglo multidimensional, necesitarás dos bucles for: uno para recorrer cada uno de los sub arreglos, y otro para recorrer los elementos de cada sub arreglo.

Recorrer los arreglos internos

Para ello, configura un bucle for como has hecho en retos anteriores.

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

Tenga en cuenta que estamos utilizando let en lugar de var para el bucle y para declarar el product. En este reto no notarás la diferencia entre ambos, pero en general es una buena práctica usar const y let de ES6 siempre que puedas. Puedes leer más sobre por qué en este artículo.

Ahora registra cada uno de los sub arreglos en la consola:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    console.log(arr[i]);
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

Como estás llamando a multiplyAll() con [[1,2],[3,4],[5,6,7]] en la parte inferior debe ver lo siguiente:

[ 1, 2 ]
[ 3, 4 ]
[ 5, 6, 7 ]

Recorrer en bucle los elementos de cada sub arreglo

Ahora tienes que recorrer cada número de los sub arreglos que acabas de registrar en la consola.

Elimina console.log(arr[i]); y crea otro bucle for dentro del que acabas de escribir:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      
    }
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

Recuerda que, para el bucle interno, necesitamos comprobar la .length de arr[i], ya que arr[i] es uno de los sub arreglos que vimos antes.

Ahora registra arr[i][j] en la consola para ver cada uno de los elementos individuales:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      console.log(arr[i][j]);
    }
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);
1
2
3
4
5
6
7

Por último, multiplica el product por cada elemento de cada uno de los sub arreglos:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      product *= arr[i][j];
    }
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

Si registras el product en la consola, verás la respuesta correcta para cada caso de prueba:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    for (let j = 0; j < arr[i].length; j++) {
      product *= arr[i][j];
    }
  }
  // Cambia sólo el código antes de esta línea
  console.log(product);
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);
6  // [[1], [2], [3]]
5040  // [[1, 2], [3, 4], [5, 6, 7]]
54  // [[5, 1], [0.2, 4, 0.5], [3, 9]]

Un vistazo más de cerca

Si todavía no estás seguro de por qué funciona el código anterior, no te preocupes: no estás solo. Trabajar con bucles anidados es complicado, e incluso los desarrolladores experimentados pueden confundirse.

En casos como este, puede ser útil registrar algo más detallado en la consola. Vuelve a tu código y registra `Sub-array ${i}: ${arr[i]}` en la consola justo antes del bucle for interno:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    console.log(`Sub-array ${i}: ${arr[i]}`);
    for (let j = 0; j < arr[i].length; j++) {
      product *= arr[i][j];
    }
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

En el bucle for exterior, cada iteración recorre las submatrices de arr. Deberías ver esto en la consola:

Sub-array 0: 1,2
Sub-array 1: 3,4
Sub-array 2: 5,6,7

Ten en cuenta que estamos utilizando literales de plantilla arriba. `Sub-array ${i}: ${arr[i]}` es lo mismo que `Sub-array ' + i + ': ' + arr[i], solo que mucho más fácil de escribir.

Ahora, en el bucle for interno, registra `Element ${j}: ${arr[i][j]}` en la consola:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    console.log(`Sub-array ${i}: ${arr[i]}`);
    for (let j = 0; j < arr[i].length; j++) {
      console.log(`Element ${j}: ${arr[i][j]}`);
      product *= arr[i][j];
    }
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

El bucle for interno recorre cada elemento de cada sub arreglo (arr[i]), por lo que deberías ver esto en la consola:

Sub-array 0: 1,2
Element 0: 1
Element 1: 2
Sub-array 1: 3,4
Element 0: 3
Element 1: 4
Sub-array 2: 5,6,7
Element 0: 5
Element 1: 6
Element 2: 7

La primera iteración de i toma el primer sub arreglo, [1, 2]. Y después, la primera iteración de j recorre cada elemento de ese sub arreglo:

// i is 0
arr[0] // [1, 2];

// j is 0
arr[0][0] // 1
// j is 1
arr[0][1] // 2

-----

// i is 1
arr[1] // [3, 4]

// j is 0
arr[1][0] // 3
// j is 1
arr[1][1] // 4

...

Este ejemplo es bastante simple, pero arr[i][j] todavía puede ser difícil de entender sin registrar varias cosas en la consola.

Una mejora rápida que podemos hacer es declarar una variable subArray en el bucle for externo y hacerla igual a arr[i]:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    const subArray = arr[i];
    for (let j = 0; j < arr[i].length; j++) {
      product *= arr[i][j];
    }
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

Luego, solo tienes que hacer algunos ajustes en el código para utilizar la nueva variable subArray en lugar de arr[i]:

function multiplyAll(arr) {
  let product = 1;
  // Sólo cambie el código inferior a esta línea
  for (let i = 0; i < arr.length; i++) {
    const subArray = arr[i];
    for (let j = 0; j < subArray.length; j++) {
      product *= subArray[j];
    }
  }
  // Cambia sólo el código antes de esta línea
  return product;
}

multiplyAll([[1,2],[3,4],[5,6,7]]);

Esto debería ser todo lo que necesitas saber sobre arreglos multidimensionales y bucles for anidados. Ahora, ¡vete a hacer iteraciones como los mejores!