Ordenar y Revertir el Orden de los Arreglos
Aplanar Arreglos Anidados: flat() y flatMap()
🥞 Arreglos Dentro de Arreglos
A veces nos encontramos con arreglos que contienen otros arreglos como elementos. A esto se le llama un arreglo anidado.
let matriz = [ [1, 2, 3], [4, 5, 6], [7, 8, 9],];
let listas = ["a", "b", ["c", "d"], "e"];
En ciertas situaciones, queremos “deshacer” esta anidación y obtener un solo arreglo con todos los elementos. A esto le llamamos aplanar (flattening).
flat()
: Aplanando por Niveles
El método flat()
crea un nuevo arreglo con todos los elementos de los sub-arreglos concatenados recursivamente hasta una profundidad especificada.
Aplanado Básico (Profundidad 1)
Por defecto, flat()
aplana solo un nivel de profundidad.
let arregloSimpleAnidado = [1, 2, [3, 4], 5];let aplanadoSimple = arregloSimpleAnidado.flat();console.log(aplanadoSimple); // Muestra [1, 2, 3, 4, 5]
let masAnidado = [1, [2, [3, [4]]], 5];let aplanadoNivel1 = masAnidado.flat(); // Solo aplana el primer nivelconsole.log(aplanadoNivel1); // Muestra [1, 2, [3, [4]], 5]
Especificando la Profundidad
Podemos pasar un argumento numérico a flat()
para indicar cuántos niveles queremos aplanar.
let muyAnidado = [1, [2, [3, [4, [5]]]]];
let aplanadoNivel2 = muyAnidado.flat(2);console.log(aplanadoNivel2); // Muestra [1, 2, 3, [4, [5]]]
let aplanadoNivel3 = muyAnidado.flat(3);console.log(aplanadoNivel3); // Muestra [1, 2, 3, 4, [5]]
Aplanado Completo (Infinity
)
Si queremos aplanar todos los niveles, sin importar cuán profundo sea el anidamiento, podemos pasar Infinity
como argumento.
let superAnidado = [1, [2, [3, [4, [5, [6]]]]]];let aplanadoTotal = superAnidado.flat(Infinity);console.log(aplanadoTotal); // Muestra [1, 2, 3, 4, 5, 6]
💡 flat()
también elimina los “empty slots” o agujeros del arreglo durante el aplanado.
let conAgujeros = [1, , 3, [4, , 6]];console.log(conAgujeros.flat()); // Muestra [1, 3, 4, 6]
flatMap()
: Mapear y Aplanar en Uno
Es muy común querer aplicar una función a cada elemento de un arreglo (como con map()
) y luego aplanar el resultado inmediatamente (porque la función de mapeo podría devolver arreglos).
El método flatMap()
hace exactamente eso: primero mapea cada elemento usando una función, y luego aplana el resultado en un nivel de profundidad. Es equivalente a llamar map()
seguido de flat(1)
, pero es más eficiente.
let frases = ["Hola mundo", "Adiós amigos"];
// Queremos un arreglo con todas las palabras individuales
// Usando map y flat por separado:let palabrasMap = frases.map((frase) => frase.split(" ")); // Devuelve [["Hola", "mundo"], ["Adiós", "amigos"]]let palabrasFlat = palabrasMap.flat(); // Devuelve ["Hola", "mundo", "Adiós", "amigos"]console.log(palabrasFlat);
// Usando flatMap:let palabrasFlatMap = frases.flatMap((frase) => frase.split(" ")); // Hace ambos pasosconsole.log(palabrasFlatMap); // Muestra ["Hola", "mundo", "Adiós", "amigos"]
Otro ejemplo: duplicar cada número en un arreglo.
let numeros = [1, 2, 3];
let duplicados = numeros.flatMap((num) => [num, num * 2]);// Paso 1 (map imaginario): [[1, 2], [2, 4], [3, 6]]// Paso 2 (flat(1)): [1, 2, 2, 4, 3, 6]console.log(duplicados);
⚠️ Recuerda que flatMap()
solo aplana un nivel. Si tu función de mapeo
devuelve arreglos muy anidados, flatMap()
no los aplanará por completo.
☝️🤓
🏋️♂️ Ejercicio
Dado el arreglo: let data = [[1, 2], [3, 4, 5], [], [6]];
- Usa
flat()
para crear un nuevo arreglodataAplanada
que contenga todos los números en un solo nivel. - Muestra
dataAplanada
por consola.
🏋️♂️ Ejercicio
Dado el arreglo: let items = [ { nombre: "A", tags: ["t1", "t2"] }, { nombre: "B", tags: ["t3"] }, { nombre: "C", tags: ["t2", "t4"] } ];
- Usa
flatMap()
para obtener un único arreglotodosLosTags
que contenga todos los tags de todos los items, sin duplicados si es posible (pista: puedes usarSet
después delflatMap
o investigar cómo hacerlo directamente). - Muestra
todosLosTags
por consola.
🚀 Extra
Investiga sobre:
- ¿Cuál es la ganancia de rendimiento de
flatMap()
comparado conmap().flat()
? - ¿Cómo podrías implementar tu propia función
miFlat(arreglo, profundidad)
que imite el comportamiento deflat()
usando recursión o iteración? - Considera el arreglo
[1, 2, , 4, [5, , 7]]
. ¿Cuál sería el resultado de aplicarflat()
yflatMap(x => [x * 2])
? Analiza el manejo de los empty slots.