13.2 Common Iterator Methods

Rust provides a rich set of iterator adapters and consuming methods for efficient data processing. Below are some of the most commonly used methods, along with examples.

13.2.1 Iterator Adapters

These methods are lazy and transform one iterator into another iterator without actually processing the items until consumed.

map()

Transforms each element by applying a closure or function.

Syntax:

#![allow(unused)]
fn main() {
iterator.map(|element| transformation)
}

Example:

fn main() {
    let numbers = vec![1, 2, 3, 4];
    let doubled: Vec<i32> = numbers.iter().map(|x| x * 2).collect();
    println!("{:?}", doubled); // Output: [2, 4, 6, 8]
}

Note that passing a function instead of a closure to map() is possible if the function's signature matches:

fn dup(i: &i32) -> i32 {i * 2}
fn main() {
    let numbers = vec![1, 2, 3, 4];
    let doubled: Vec<i32> = numbers.iter().map(dup).collect();
    println!("{:?}", doubled); // Output: [2, 4, 6, 8]
}

filter()

Selects elements that satisfy a predicate.

Syntax:

#![allow(unused)]
fn main() {
iterator.filter(|element| predicate)
}

Example:

fn main() {
    let numbers = vec![1, 2, 3, 4, 5, 6];
    let even_nums: Vec<i32> = numbers.iter().filter(|&x| x % 2 == 0).cloned().collect();
    println!("{:?}", even_nums); // Output: [2, 4, 6]
}

take()

Limits the number of elements in an iterator to a specified count.

Syntax:

#![allow(unused)]
fn main() {
iterator.take(count)
}

Example: Taking the First Three Elements

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    let first_three: Vec<i32> = numbers.iter().take(3).cloned().collect();
    println!("{:?}", first_three); // Output: [1, 2, 3]
}

skip()

Skips a specified number of elements and returns the rest.

Syntax:

#![allow(unused)]
fn main() {
iterator.skip(count)
}

Example: Skipping the First Two Elements

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    let skipped: Vec<i32> = numbers.iter().skip(2).cloned().collect();
    println!("{:?}", skipped); // Output: [3, 4, 5]
}

enumerate()

Adds an index to each element, returning a tuple (index, element).

Syntax:

#![allow(unused)]
fn main() {
iterator.enumerate()
}

Example: Enumerating Elements with Their Indices

fn main() {
    let names = vec!["Alice", "Bob", "Charlie"];
    for (index, name) in names.iter().enumerate() {
        print!("{}: {}; ", index, name);
    }
    // Output: 0: Alice; 1: Bob; 2: Charlie;
}

13.2.2 Consuming Iterator Methods

These methods process the items of the collection, consuming or exhausting the iterator.

sum()

Computes the sum of elements.

Syntax:

#![allow(unused)]
fn main() {
iterator.sum::<Type>()
}

Example:

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];
    let total: i32 = numbers.iter().sum();
    println!("Total: {}", total); // Output: Total: 15
}

fold()

Accumulates values by applying a function, starting from an initial value.

Syntax:

#![allow(unused)]
fn main() {
iterator.fold(initial_value, |accumulator, element| operation)
}

Example:

fn main() {
    let numbers = vec![1, 2, 3, 4];
    let product = numbers.iter().fold(1, |acc, &x| acc * x);
    println!("{}", product); // Output: 24
}

for_each()

Applies a function to each element.

Syntax:

#![allow(unused)]
fn main() {
iterator.for_each(|element| { /* action */ })
}

Example:

fn main() {
    let numbers = vec![1, 2, 3];
    numbers.iter().for_each(|x| print!("{}, ", x));
    // Output: 1, 2, 3, 
}