簡體   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