Rust 堆叠可选在 while let

epo*_*och 2 rust

我真的是 Rust 的新手,在进行 rustlings 练习时,我发现了一些我对堆叠选项不完全理解的东西。

鉴于以下代码:

let vector = vec![Some(24), None, Some(42)];
let mut iter = vector.iter();
while let Some(Some(number)) = iter.next() {
    println!("Number: {}", number);
}
Run Code Online (Sandbox Code Playgroud)

我希望看到以下输出:

Number: 24
Number: 42
Run Code Online (Sandbox Code Playgroud)

但我想只要 rust 遇到None,while 循环就会退出,只打印 24

迭代和解包可选值的最惯用的 Rust 代码是什么?我得到的最接近的看起来像这样:

let mut iter = vector.iter();
while let Some(iterNext) = iter.next() {
    if let Some(num) = iterNext {
        println!("Number: {}", num);
    }
}
Run Code Online (Sandbox Code Playgroud)

或者也可以通过检查 for 循环中的存在来完成:

for opt in &vector {
    if opt.is_some() {
        println!("Number: {}", opt.unwrap());
    }
}
Run Code Online (Sandbox Code Playgroud)

Sve*_*ach 6

编写此代码的另一种好方法是

for num in vector.iter().flatten() {
    println!("{}", num);
}
Run Code Online (Sandbox Code Playgroud)

flatten()上一个迭代治疗方法迭代器作为一个迭代的每个项目,并返回在所有这些迭代器链接在一起的迭代器。Option是产生一个元素,如果它是一个迭代器Some,或none None,所以flatten()是eactly我们在这里想要的。

当然,您也可以使用 编写它for_each(),但是对于具有副作用的代码,我通常更喜欢for循环。


use*_*342 5

我希望看到以下输出:[...]

一个while循环,遇到一个假条件退出-但这不是具体去锈,它只是如何while循环工作。

惯用的解决方案可能会结合您的最后两个片段:

for opt in &vector {
    if let Some(num) = opt {
        println!("Number: {}", num);
    }
}
Run Code Online (Sandbox Code Playgroud)

只是一个for包含 的简单循环if let,不需要展开。

另一个惯用的变体是使用迭代器适配器:

vector
    .iter()
    .filter_map(|opt| opt.as_ref())
    .for_each(|num| println!("{}", num));
Run Code Online (Sandbox Code Playgroud)

请注意,在这里我们可以使用filter(Option::is_some),但是我们将剩下选项并且必须使用unwrap()来获取值。这就是 filter_map()有用的地方:它过滤Some值(在应用 map 函数之后),同时提取里面的值。opt.as_ref()用于简单地转换&Option<T>,通过引用迭代选项向量获得Option<&T>filter_map期望返回。