首页 > 解决方案 > `(i, &item)` 在使用 enumerate() 的 for 循环中是什么意思?

问题描述

我正在阅读 Rust 文档,我看到了这段代码:

fn first_word(s: &String) -> &str {
    let bytes = s.as_bytes();
    println!("{:?}", bytes.iter().enumerate());

    for (i, &item) in bytes.iter().enumerate() {
        println!("{}", i);
        if item == b' ' {
            print!("{}", &s[0..i]);
            break;
        }
    }

    &s[..]
}


fn main() {
    let amir = String::from("amir ali ahmadi");
    first_word(&amir);
    println!("{:?}", b" ")
}

为什么是i索引?

为什么是&item价值?

标签: rust

解决方案


当你调用enumerate()一个迭代器时,你会得到一个 的实例Enumerate,它的结构定义如下:

pub struct Enumerate<I> {
    iter: I,
    count: usize,
}

换句话说,Enumerate简单地包装原始迭代器以及一个count跟踪将从迭代器获取的下一个索引的字段。(在 Enumerate 文档中有指向源代码的链接。)

每次for循环调用next()Enumerate,它都会执行此方法:

fn next(&mut self) -> Option<(usize, <I as Iterator>::Item)> {
    let a = self.iter.next()?;
    let i = self.count;
    // Possible undefined overflow.
    AddAssign::add_assign(&mut self.count, 1);
    Some((i, a))
}

这将返回一个Option::Some包含 tuple 的(i, a)。的值i等于count字段,因此等于当前迭代器索引。并且 的值a等于对iter.next()原始迭代器的调用返回的值。该add_assign函数具有将count字段值增加 1 的效果。

请注意,?调用后的iter.next()意思是如果迭代器不再包含项目,Option::None则将改为返回,并且该方法将完成。

正如对您的问题的评论中所指出的,当您打印Enumerate实例的调试输出时,您将看到嵌套的迭代器和count字段:

{
    iter: Iter([97, 109, 105, 114, 32, 97, 108, 105, 32, 97, 104, 109, 97, 100, 105]),
    count: 0
}

推荐阅读