Aplanando Arrays en JavaScript con flat()
Imagina que tienes una lista con varios elementos, pero algunos de ellos también son listas dentro de la lista principal. Algo así:
[[3, 2], 5, 3, [3, 4, 2], 10]
Si queremos convertir todo en una sola lista plana sin sublistas anidadas, podemos usar el método flat() que ya viene en JavaScript:
[[3, 2], 5, 3, [3, 4, 2], 10].flat();
// Resultado: [3, 2, 5, 3, 3, 4, 2, 10]
Este método nos facilita mucho la vida, pero ¿qué pasa si queremos aprender cómo funciona y hacerlo nosotros mismos? Vamos a implementar nuestra propia versión.
Creando nuestra propia función flatten
Vamos a escribir una función llamada flatten que recorra una lista (array) y, si encuentra otros arrays dentro, los desempaque en la lista principal, pero solo hasta un nivel de profundidad. Es decir, si dentro de esos arrays hay otros arrays más profundos, no los tocará.
Paso 1: Recorrer cada elemento del array
Para esto, usamos un for..of, que nos permite recorrer cada elemento del array principal:
const flatten = (coll) => {
const result = []; // Inicializamos un nuevo array para almacenar el resultado
for (const item of coll) { // Iteramos sobre cada elemento
if (Array.isArray(item)) { // Verificamos si el elemento es un array
for (const subItem of item) { // Si es un array, lo recorremos
result.push(subItem); // Agregamos cada elemento de este subarray a nuestro resultado
}
} else {
result.push(item); // Si no es un array, simplemente lo agregamos al resultado
}
}
return result;
};
console.log(flatten([3, 2, [], [3, 4, 2], 3, [123, 3]]));
// Resultado: [3, 2, 3, 4, 2, 3, 123, 3]
Explicación del código
- Verificamos si el elemento es un array usando
Array.isArray(item).- Si no es un array, lo agregamos directamente al resultado (
result.push(item)). - Si es un array, recorremos sus elementos internos y los agregamos al resultado.
- Si no es un array, lo agregamos directamente al resultado (
Entendiendo los bucles anidados
En nuestro código, tenemos un bucle dentro de otro:
- El primer bucle (
for..of coll) recorre la lista principal. - El segundo bucle (
for..of item, cuando detectamos queitemes un array) recorre los elementos del subarray.
Este tipo de estructura se llama bucles anidados (nested loops). Pueden ser muy útiles, pero también pueden hacer que el código se vuelva más difícil de leer y más costoso en rendimiento cuando se manejan datos grandes.
¿Cómo evitar los bucles anidados?
No siempre es posible evitar los bucles anidados, pero hay algunas estrategias:
- No hacer nada: Si el código es claro y eficiente, lo podemos dejar como está.
- Reescribir el algoritmo para evitar la necesidad de recorrer estructuras anidadas.
- Extraer el código repetitivo en una función aparte, lo que mejora la organización.
Extrayendo la lógica en una función separada
Podemos mejorar la organización del código extrayendo la parte que se encarga de agregar elementos a una nueva función llamada append:
const append = (arr1, arr2) => {
for (const item of arr2) {
arr1.push(item); // Recorremos y agregamos cada elemento del segundo array al primero
}
};
const flatten = (coll) => {
const result = [];
for (const item of coll) {
if (Array.isArray(item)) {
append(result, item); // Usamos la función append en lugar del bucle anidado
} else {
result.push(item);
}
}
return result;
};
console.log(flatten([3, 2, [], [3, 4, 2], 3, [123, 3]]));
// Resultado: [3, 2, 3, 4, 2, 3, 123, 3]
Aquí, append se encarga de agregar los elementos de un array a otro, reduciendo la complejidad visual de flatten.
Métodos integrados que pueden evitar bucles anidados
JavaScript ofrece métodos que internamente usan bucles, pero nos evitan escribirlos manualmente. Por ejemplo:
[1, 10, 3].includes(10); // true
El método includes() revisa si un elemento está dentro del array sin que tengamos que escribir un ciclo manualmente.
Resumen
- El método
flat()de JavaScript aplana un array eliminando un nivel de anidamiento. - Implementamos nuestra propia versión
flatten()usando unfor..ofyArray.isArray(). - Los bucles anidados pueden hacer el código más difícil de leer y menos eficiente.
- Para reducir la complejidad:
- Podemos extraer el código repetitivo en una función (
append). - Usar métodos integrados como
includes()cuando sea posible.
- Podemos extraer el código repetitivo en una función (
Si quieres seguir practicando, intenta modificar nuestra función para que aplane cualquier nivel de profundidad en lugar de solo el primer nivel. ¡Buena suerte!
Materiales adicionales
Para acceder completo a curso necesitas un plan básico
El plan básico te dará acceso completo a todos los cursos, ejercicios y lecciones de Códica, proyectos y acceso de por vida a la teoría de las lecciones completadas. La suscripción se puede cancelar en cualquier momento.