28 - Creando iteradores personalizados - optimizando el procesamiento de datos en Rust

28 - Creando iteradores personalizados - optimizando el procesamiento de datos en Rust

¡Bienvenidos de nuevo a Rustaceo.es! En esta entrega exploraremos cómo crear iteradores personalizados en Rust, una herramienta fundamental para procesar datos de manera eficiente y flexible. Los iteradores nos permiten manipular colecciones de datos sin necesidad de escribir bucles explícitos, logrando un código más conciso y expresivo. ¡Acompáñame en esta aventura!


🔄 ¿Qué es un iterador en Rust? #

Un iterador en Rust es cualquier estructura que implementa el trait Iterator. Este trait define un método clave:

trait Iterator {
    type Item;
    fn next(&mut self) -> Option<Self::Item>;
}

El método next() devuelve Some(valor) cuando hay más elementos por iterar o None cuando se ha llegado al final.


🛠 Implementando un iterador personalizado #

Imaginemos que queremos iterar sobre niveles de Pokémon que se duplican en cada paso. Podemos crear un iterador personalizado implementando Iterator.

struct NivelesDuplicados {
    nivel_actual: u32,
}

impl NivelesDuplicados {
    fn nuevo() -> Self {
        NivelesDuplicados { nivel_actual: 1 }
    }
}

impl Iterator for NivelesDuplicados {
    type Item = u32;

    fn next(&mut self) -> Option<Self::Item> {
        if self.nivel_actual > 100 {
            None // Detenemos la iteración en 100
        } else {
            let resultado = self.nivel_actual;
            self.nivel_actual *= 2; // Duplicamos el nivel
            Some(resultado)
        }
    }
}

fn main() {
    let iterador = NivelesDuplicados::nuevo();
    for nivel in iterador {
        println!("Nivel: {}", nivel);
    }
}

En este ejemplo:

  • next() retorna el nivel actual y luego lo multiplica por 2.
  • Cuando nivel_actual supera 100, retorna None para detener la iteración.
  • Podemos usar for nivel in iterador para recorrer los valores.

🎛 Métodos útiles para iteradores #

Rust proporciona múltiples métodos para trabajar con iteradores de manera eficiente.

📌 Map(): transformación de datos #

let niveles = vec![5, 10, 15];
let niveles_potenciados: Vec<_> = niveles.iter().map(|x| x * 2).collect();
println!("Niveles potenciados: {:?}", niveles_potenciados);

🔍 Filter(): filtrado de elementos #

let niveles_altos: Vec<_> = niveles.into_iter().filter(|&x| x >= 10).collect();
println!("Niveles altos: {:?}", niveles_altos);

🏆 Fold(): reducción de datos #

let suma_total: u32 = (1..=5).fold(0, |acumulado, x| acumulado + x);
println!("Suma total: {}", suma_total);

📊 Conclusión #

Crear iteradores personalizados en Rust nos permite procesar datos de manera más eficiente y elegante. Mediante la implementación de Iterator, podemos definir la lógica de iteración de forma flexible y combinarlos con métodos funcionales para lograr código más limpio y mantenible.

💡 Próximo paso: ¡Intenta crear tus propios iteradores para modelar situaciones específicas en tus proyectos de Rust!

¡Hasta la próxima, Rustaceos!