How do I enumerate a Vec of structs

I want to iterate over a Vec of structs. I can iterate without enumerating.

#[derive(Debug)]
struct Pair<'a> {
    key: &'a str,
    value: &'a str,
}

fn main() {
    let mut pairs = Vec::new();
    for key in ["A", "B", "C", "D"].iter() {
        pairs.push(Pair { key, value: "even" });
        pairs.push(Pair { key, value: "odd" });
    }
    println!("{:?}", pairs);
    for pair in &pairs {
        println!("key={} value={}", pair.key, pair.value);
    }
    // All above this works fine: below produces errors
    /*
    for (i, pair) in &pairs.iter().enumerate() {
        println!("{}: key={} value={}", i, pair.key, pair.value);
    }
    */
}

The above compiles & runs fine. But if you uncomment the last for loop, it produces these errors:

error[E0277]: the trait bound `&std::iter::Enumerate<std::slice::Iter<'_, Pair<'_>>>: std::iter::Iterator` is not satisfied
  --> src/main.rs:18:5
   |
18 | /     for (i, pair) in &pairs.iter().enumerate() {
19 | |         println!("{}: key={} value={}", i, pair.key, pair.value);
20 | |     }
   | |_____^ `&std::iter::Enumerate<std::slice::Iter<'_, Pair<'_>>>` is not an iterator; maybe try calling `.iter()` or a similar method
   |
   = help: the trait `std::iter::Iterator` is not implemented for `&std::iter::Enumerate<std::slice::Iter<'_, Pair<'_>>>`
   = note: required by `std::iter::IntoIterator::into_iter`

I've tried use std::iter::{Iterate, Enumerate} in case I needed these traits, but that didn't help.

Can someone tell me what I doing wrong please? (I know I could easily have a counter variable, but I really want to understand & do it right.)

This case is as simple as removing the &.
for (i, pair) in pairs.iter().enumerate() {
& is the latter item to be evaluated and creates a reference to the Enumerate iterator. It works in the first &pairs loop by this making a slice which supports into iterator.
A more complex case might also require the use of ref keyword.

If you want to iterate over the slice, so that the iterator does not take ownership of the Vec, you should add parenthesis like for (i, pair) in (&pairs).iter().enumerate() {

Thanks!

1 Like

That’s unnecessary - iter() takes &self and thus doesn’t consume the Vec (compiler will insert an auto-ref to make the &self for the call).

I tried &pairs & it didn't work; but (&pairs) works fine. I'm using Rust 1.24.

@mark, @jonh gave you the right formulation earlier, which I'll repeat here:

for (i, pair) in pairs.iter().enumerate() {
   println!("{}: key={} value={}", i, pair.key, pair.value);
}
1 Like

@vitalyd -- you are quite right! I'd misunderstood. That works perfectly & is of course much nicer.

Thanks!

I'm sorry. Confused with into_iter()