Rust - Iterators


Iterators allow you to perform some task on a sequence of items.

Rust iterators are lazy, they do not do anything until a method consumes them.

Collect

Converts an iterator into a collection. The type of collection must be known. Example:

let add_one: Vec<_> = vec![1,2,3].iter().map(|x| x + 1).collect();
let add_one_more = add_one.iter().map(|x| x + 1).collect::<Vec<i32>>(); // turbofish type specification

Filter

Uses a closure to filter results from an iterator. Only results that return true are added to the resulting iterator.

let even: Vec<u32> = vec![1,2,3,4].into_iter().filter(|x| x % 2 == 0).collect();

Iter

There are three common types of iter functions:

  • iter: Iterator over immutable references
  • into_iter: Takes ownership of collection and returns owned values
  • iter_mut: Iterator over mutable references
fn main() {
    let v = vec![1, 2, 3, 4];
    // iter
    let sum: i32 = v.iter().sum(); // 10
    // into_iter
    let even: Vec<i32> = v.into_iter().filter(|x| x % 2 == 0).collect(); // [2, 4]
    // iter_mut
    let mut v = &mut vec![1, 2, 3, 4];
    for x in v.iter_mut() {
        *x += 1;
    } // [2, 3, 4, 5]
}

Map

Applies a closure to an iterator and returns an iterator. Example:

let add_one: Vec<_> = vec![1,2,3].iter().map(|x| x + 1).collect();

Sum

Adds together all elements in the collection:

let total: i32 = vec![1, 2, 3].iter().sum(); // 6

Traits

All iterators implement a trait named Iterator, which is defined in the standard library. The definition follows:

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

Zip

Iterates over two iterators simultaneously.

let x = vec![1, 2, 3, 4];
    let y = vec![9, 8, 7, 6];

    let z: Vec<i32> = x.iter().zip(y).map(|(a, b)| a + b).collect();

    assert_eq!(z, vec![10, 10, 10, 10]);