Rust enumerate Example: A Comprehensive Guide

The enumerate method in Rust is a powerful tool for iterating over a collection while keeping track of the index of each item. This method is particularly useful in scenarios where both the item and its position within the collection are needed.

In this article, we’ll explore how to use enumerate effectively with practical examples.


What is enumerate in Rust?

The enumerate method is part of the Rust Iterator trait. It transforms an iterator into a new iterator that yields pairs (index, item), where:

  • index is the zero-based position of the item in the collection.
  • item is the value of the current element.

Signature

fn enumerate(self) -> Enumerate<Self>
  • self: The original iterator.
  • Returns: An iterator yielding (usize, T) tuples, where usize is the index, and T is the item type.

Basic Usage of enumerate

Here’s a simple example to demonstrate how enumerate works.

fn main() {
    let fruits = vec!["apple", "banana", "cherry"];

    for (index, fruit) in fruits.iter().enumerate() {
        println!("Index: {}, Fruit: {}", index, fruit);
    }
}

Output

Index: 0, Fruit: apple
Index: 1, Fruit: banana
Index: 2, Fruit: cherry

Practical Examples

1. Modify Elements Using Index

Use enumerate to modify elements in a mutable collection based on their index.

fn main() {
    let mut numbers = vec![10, 20, 30];

    for (index, number) in numbers.iter_mut().enumerate() {
        *number += index;
    }

    println!("{:?}", numbers);
}

Output

[10, 21, 32]

2. Filtering Based on Index

Filter elements based on their index using enumerate.

fn main() {
    let numbers = vec![1, 2, 3, 4, 5];

    let even_indexed_numbers: Vec<_> = numbers
        .iter()
        .enumerate()
        .filter(|(index, _)| index % 2 == 0)
        .map(|(_, &num)| num)
        .collect();

    println!("{:?}", even_indexed_numbers);
}

Output

[1, 3, 5]

3. Working with Strings

Use enumerate to iterate over characters in a string with their indices.

fn main() {
    let word = "Rust";

    for (index, char) in word.chars().enumerate() {
        println!("Index: {}, Char: {}", index, char);
    }
}

Output

Index: 0, Char: R
Index: 1, Char: u
Index: 2, Char: s
Index: 3, Char: t

4. Nested Loops with enumerate

Handle nested loops where indices are important for both levels.

fn main() {
    let matrix = vec![
        vec![1, 2, 3],
        vec![4, 5, 6],
        vec![7, 8, 9],
    ];

    for (row_index, row) in matrix.iter().enumerate() {
        for (col_index, value) in row.iter().enumerate() {
            println!("Row: {}, Col: {}, Value: {}", row_index, col_index, value);
        }
    }
}

Output

Row: 0, Col: 0, Value: 1
Row: 0, Col: 1, Value: 2
Row: 0, Col: 2, Value: 3
Row: 1, Col: 0, Value: 4
Row: 1, Col: 1, Value: 5
Row: 1, Col: 2, Value: 6
Row: 2, Col: 0, Value: 7
Row: 2, Col: 1, Value: 8
Row: 2, Col: 2, Value: 9

Common Use Cases for enumerate

  1. Debugging:
    • Print the index and value of each element in a collection for troubleshooting.
  2. Index-Based Operations:
    • Perform calculations or modifications based on the position of elements.
  3. Data Transformation:
    • Map elements along with their indices into a new structure.
  4. Filtering:
    • Select elements based on their index or a combination of index and value.

Best Practices

  1. Use .iter_mut() for Mutable Iterators:
    • Use .iter_mut() with enumerate when modifying elements in a collection.
  2. Destructure Tuples for Clarity:
    • Clearly destructure (index, value) pairs for readability.
  3. Combine with Other Iterator Methods:
    • Chain enumerate with methods like filter, map, or collect for powerful transformations.
  4. Avoid Manual Index Tracking:
    • Instead of manually maintaining an index variable, use enumerate for cleaner and safer code.

Conclusion

Rust’s enumerate method is a versatile tool for iterating over collections while keeping track of indices. It simplifies many tasks by eliminating the need for manual index tracking and integrates seamlessly with Rust’s iterator ecosystem. By mastering enumerate, you can write cleaner, more efficient, and more expressive code.