繁体   English   中英

Rust 在 while let 中堆叠可选

[英]Rust stacked optional in while let

我真的是 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);
}

我希望看到以下输出:

Number: 24
Number: 42

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

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

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

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

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

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

for num in vector.iter().flatten() {
    println!("{}", num);
}

迭代器上的flatten()方法将迭代器的每个项目视为一个迭代器,并返回一个迭代器,该迭代器覆盖所有链接在一起的迭代器。 Option是一个迭代器,如果它是Some则产生一个元素,或者 None 为None ,所以flatten()正是我们想要的。

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

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

遇到错误条件的while循环退出 - 但这不是 Rust 特有的,它只是while循环的工作方式。

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

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

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

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

vector
    .iter()
    .filter_map(|opt| opt.as_ref())
    .for_each(|num| println!("{}", num));

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

使用and_then过滤掉None并且只将Some传递给程序工作部分:

let vector = vec![Some(24), None, Some(42)];
for num in vector.iter() {
    num.and_then::<i32, fn(i32) -> Option<i32>>(|n| {
        println!("{}", n);  // …working part
        None
    });
}

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM