Dominio de la Lógica de Programación y Estructuras
Estructuras de Datos Dinámicas
Estructuras que cobran vida
Has trabajado con arreglos y objetos para almacenar datos. Ahora, vamos a verlos como herramientas dinámicas para modelar la realidad. En lugar de simplemente guardar información, aprenderás a transformar y gestionar estados complejos, tal como lo hacen las aplicaciones del mundo real. La clave no está en qué guardan, sino en cómo los manipulamos eficientemente.
Transformación funcional de arreglos
En lugar de usar bucles for tradicionales para recorrer arreglos, los métodos funcionales nos permiten escribir un código más declarativo y predecible. Estos métodos (map, filter y reduce) no modifican el arreglo original; en su lugar, devuelven uno nuevo. Esta práctica se conoce como y es fundamental para prevenir errores inesperados en aplicaciones complejas.
map es perfecto para transformar cada elemento de un arreglo. Imagina que tienes una lista de productos y solo quieres sus nombres:
const productos = [
{ id: 1, nombre: 'Laptop', precio: 1200 },
{ id: 2, nombre: 'Mouse', precio: 25 },
{ id: 3, nombre: 'Teclado', precio: 75 }
];
const nombres = productos.map(producto => producto.nombre);
console.log(nombres); // ['Laptop', 'Mouse', 'Teclado']
filter, como su nombre indica, crea un nuevo arreglo con solo los elementos que cumplen una condición específica. Si queremos solo los productos que cuestan más de $50:
const productosCaros = productos.filter(producto => producto.precio > 50);
console.log(productosCaros);
// [ { id: 1, nombre: 'Laptop', precio: 1200 }, { id: 3, nombre: 'Teclado', precio: 75 } ]
Finalmente, reduce es el más versátil. "Reduce" un arreglo a un solo valor, que puede ser un número, un objeto o incluso otro arreglo. Usemos reduce para calcular el costo total del inventario:
const costoTotal = productos.reduce((acumulador, producto) => {
return acumulador + producto.precio;
}, 0); // El 0 es el valor inicial del acumulador
console.log(costoTotal); // 1295
Estos tres métodos se pueden encadenar para realizar operaciones complejas de forma muy legible. Por ejemplo,
productos.filter(...).map(...).reduce(...).
Desempacando datos al instante
Acceder a datos dentro de objetos y arreglos anidados puede volverse verboso. La es una sintaxis de JavaScript que nos permite extraer datos de manera concisa.
Para objetos, extraemos propiedades por su nombre:
const usuario = {
nombre: 'Ana',
edad: 28,
info: { email: 'ana@example.com' }
};
// Extraemos nombre y el email anidado
const { nombre, info: { email } } = usuario;
console.log(nombre); // 'Ana'
console.log(email); // 'ana@example.com'
Para arreglos, extraemos elementos por su posición:
const coordenadas = [10.4, -75.5, 'Cartagena'];
const [lat, lng, ciudad] = coordenadas;
console.log(lat); // 10.4
console.log(ciudad); // 'Cartagena'
El costo de la búsqueda
Cuando trabajas con grandes volúmenes de datos, la eficiencia importa. No todas las operaciones tienen el mismo costo computacional. Imagina que tienes un arreglo con miles de usuarios y necesitas encontrar uno por su id.
Si usas el método find(), en el peor de los casos, la computadora tendrá que recorrer todos los elementos hasta encontrar el que buscas. Esta operación tiene una complejidad de tiempo que llamamos , donde es el número de elementos en el arreglo. A medida que el arreglo crece, el tiempo de búsqueda crece linealmente.
Ahora, ¿qué pasaría si en lugar de un arreglo, tuviéramos los usuarios en un objeto, donde la llave es el id del usuario?
const usuariosObjeto = {
'101': { nombre: 'Carlos', edad: 30 },
'102': { nombre: 'Beatriz', edad: 25 },
// ... miles de usuarios
};
// La búsqueda es directa
const usuarioBuscado = usuariosObjeto['102'];
En este caso, la búsqueda es casi instantánea, sin importar cuántos usuarios haya. Esto se debe a que los objetos en JavaScript se implementan usando una estructura llamada que permite el acceso directo a los elementos por su llave. Esta operación tiene una complejidad de tiempo de , o tiempo constante.
La elección entre un arreglo y un objeto para almacenar colecciones de datos depende de tu caso de uso. Si necesitas mantener un orden o iterar sobre todos los elementos frecuentemente, un arreglo es ideal. Si tu prioridad es la búsqueda rápida por un identificador único, un objeto es mucho más eficiente.
Dado el siguiente arreglo: const productos = [{ id: 1, nombre: 'Laptop', stock: 15 }, { id: 2, nombre: 'Mouse', stock: 0 }, { id: 3, nombre: 'Teclado', stock: 30 }];. ¿Cuál de las siguientes opciones crea correctamente un nuevo arreglo solo con los productos que tienen stock disponible (stock > 0)?
El principio de [{map y filter significa que estos no modifican el arreglo original, sino que devuelven uno nuevo.
Ahora que entiendes cómo manipular y evaluar estas estructuras, estás un paso más cerca de escribir código no solo funcional, sino también optimizado.