Iterators

map()

The .map() adapter transforms each element of an iterator by applying an FnMut(Self::Item) -> B closure, returning a lazy std::iter::Map<Self, F> iterator that yields the transformed values of type B.

Signature

fn map<B, F>(self, f: F) -> Map<Self, F>
where
    Self: Sized,
    F: FnMut(Self::Item) -> B,

Each time .next() is called on Map<Self, F>, it pulls one item from the underlying iterator:

  • If the inner iterator returns Some(x), Map returns Some(f(x)).
  • If the inner iterator returns None, Map returns None.
Source: [ 1,   2,   3 ]
          │    │    │   .map(|x| x * 10)
          ▼    ▼    ▼
Output: [ 10,  20,  30 ]

Transforming Values and Changing Types

The output type B does not need to match the input type Self::Item:

fn main() {
    let radii = [1.0_f64, 2.5, 4.0];

    // Transforms `f64` -> formatted `String`:
    let labels: Vec<String> = radii
        .into_iter()
        .map(|r| {
            let area = std::f64::consts::PI * r * r;
            format!("r={r:.1} -> area={area:.2}")
        })
        .collect();

    for label in &labels {
        println!("{label}");
    }
}
r=1.0 -> area=3.14
r=2.5 -> area=19.63
r=4.0 -> area=50.27

Passing Named Functions or Tuple Struct Constructors to .map()

Because named functions and tuple struct / enum variant constructors (Some, Ok, Bytes) implement Fn(A) -> B, you can pass them directly to .map() without wrapping them in a closure:

#[derive(Debug)]
struct UserId(u64);

fn main() {
    let raw_ids = [101_u64, 102, 103];
    let words = ["  alpha ", " beta  "];

    // 1. Passing tuple-struct constructor `UserId` directly:
    let users: Vec<UserId> = raw_ids.into_iter().map(UserId).collect();

    // 2. Passing method path `str::trim` directly:
    let trimmed: Vec<&str> = words.into_iter().map(str::trim).collect();

    println!("Users:   {users:?}");
    println!("Trimmed: {trimmed:?}");
}
Users:   [UserId(101), UserId(102), UserId(103)]
Trimmed: ["alpha", "beta"]

Preserving ExactSizeIterator and DoubleEndedIterator

Because .map() is a strict 1-to-1 transformation (1 input item produces 1 output item), Map<I, F> implements ExactSizeIterator whenever I: ExactSizeIterator and DoubleEndedIterator whenever I: DoubleEndedIterator. This allows .collect::<Vec<_>>() after .map() to pre-allocate the exact output capacity in a single heap allocation.