了解在迭代器上调用方法两次时如何满足借用检查器?

Understanding how to satisfy borrow checker when calling method on iterator twice?

在下面的代码中,我了解到通过 zipped.filter 的调用已经完成了借用。我不明白的是如何修复它,如果我以后想再次使用 zipped

我是 Rust 的新手,所以如果在这段代码中有其他问题或奇怪的习语误用,我也对此很感兴趣,但主要是关于如何在这里使借用工作两次。

代码:

fn main() {
    let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];

    for s1 in &data {
        for s2 in &data {
            let zipped = s2.chars().zip(s1.chars());

            // Did a diff of the two strings have only one character different?
            if zipped.filter(|(a,b)| a != b).count() == 1 {
                let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();

                println!("String without the different character: {}", newStr);
            }
        }
    }
}

错误:

error[E0382]: use of moved value: `zipped`
   --> a.rs:10:30
    |
6   |             let zipped = s2.chars().zip(s1.chars());
    |                 ------ move occurs because `zipped` has type `Zip<Chars<'_>, Chars<'_>>`, which does not implement the `Copy` trait
...
9   |             if zipped.filter(|(a,b)| a != b).count() == 1 {
    |                       ---------------------- `zipped` moved due to this method call
10  |                 let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();
    |                              ^^^^^^ value used here after move
    |
note: this function consumes the receiver `self` by taking ownership of it, which moves `zipped`

error: aborting due to previous error

For more information about this error, try `rustc --explain E0382`.

您始终可以 zipped.clone(),它会克隆迭代器,以便您在首次调用 filter(...).count() 时移动克隆。原始 zipped 保持不变,您将把它移动到第二个 filter(...).collect() .

请注意,它不会克隆任何数据,因为迭代器是惰性的,复制迭代器意味着复制其逻辑(因此它复制了 .chars().zip() 等逻辑,这只是一堆函数指针,而不是数据)。

fn main() {
    let data : Vec<String> = vec!["abc".to_string(), "def".to_string(), "bbc".to_string()];

    for s1 in &data {
        for s2 in &data {
            let zipped = s2.chars().zip(s1.chars());
            
            // << THE CHANGE IS HERE
            if zipped.clone().filter(|(a,b)| a != b).count() == 1 {
                let newStr = zipped.filter(|(a,b)| a == b).map(|(a,_)| a).collect::<String>();

                println!("String without the different character: {}", newStr);
            }
        }
    }
}

输出:

String without the different character: bc
String without the different character: bc