【问题标题】:E0597 trying to loop over an vectorE0597 试图循环一个向量
【发布时间】:2021-02-10 22:27:11
【问题描述】:

我正在通过一些编程练习自学 Rust。在这里,我有一个Vec<String> 我从一个文件中读出,我试图将每一行中的字母放在HashSet 中,然后取所有行的交集。

当我这样做时,我收到一个错误,说我的循环变量的寿命不够长。

我有一个直觉,哪里出了问题——我有一个变量l,它的生命周期是循环的一次迭代,另一个变量候选者的生命周期是整个循环,第二个变量是从第一个变量借来的。但是我该如何解决呢?

let mut candidates = HashSet::<&u8>::new();
let mut sum = 0;
for l in lines { // lines is Vec<String>
    if candidates.len()==0 {
        candidates = HashSet::<&u8>::from_iter(l.as_bytes());
        println!("candidates = {:?}", candidates);
    } else if l.len() == 0 { // error message "borrow later used here"
        // end of group
        sum = sum + candidates.len();
        candidates = HashSet::<&u8>::new();
    } else {
        let h2 = HashSet::<&u8>::from_iter(l.as_bytes()); // error message "borrowed value does not live long enough"
        candidates = candidates.intersection(&h2).copied().collect();
        println!("candidates = {:?}", candidates);
    }
    println!("{}", l);
}

我尝试复制l

let mut l2:String = "".to_string();
for l in lines {
    if candidates.len()==0 {
        l2 = l.to_string();
        candidates = HashSet::<&u8>::from_iter(l2.as_bytes());

但我得到一个不同的错误说error[E0506]: cannot assign to l2 because it is borrowed

【问题讨论】:

  • 你能像for l in &amp;lines {那样借用吗?

标签: loops rust set lifetime borrow-checker


【解决方案1】:

candidates 可以包含对上一次循环迭代中的l 的引用,但l 在每次循环迭代结束时被删除,因此会出现编译错误。您可以通过使用into_bytes 而不是as_bytes 来避免所有这些麻烦,这样您就可以获得拥有的值而不是引用。这是一个清理后的重构版本:

use std::collections::HashSet;

fn example(lines: Vec<String>) {
    let mut candidates: HashSet<u8> = HashSet::new();
    let mut sum = 0;

    for line in lines {
        dbg!(&line);
        let h2: HashSet<u8> = line.into_bytes().into_iter().collect();
        if candidates.is_empty() {
            candidates = h2;
        } else if h2.is_empty() {
            sum += candidates.len();
            candidates = HashSet::new();
        } else {
            candidates = candidates.intersection(&h2).copied().collect();
        }
        dbg!(&candidates);
    }
}

playground

【讨论】:

  • 此解决方案的另一个优点是u8&amp;u8 更小更快。
【解决方案2】:

as_bytes 将您的 l 字符串转换为字节切片。切片是对连续元素序列的引用。编译器指出,在你的 for 循环结束时,引用是无效的。

一种解决方案是使用&amp;lines 遍历字符串引用:

    let mut candidates = HashSet::<&u8>::new();
    let mut sum = 0;
    for l in &lines { // <= HERE iter over String references which lives outside the for loop
        if candidates.len()==0 {
            candidates = HashSet::<&u8>::from_iter(l.as_bytes());
            println!("candidates = {:?}", candidates);
        } else if l.len() == 0 {
            // end of group
            sum = sum + candidates.len();
            candidates = HashSet::<&u8>::new();
        } else {
            let h2 = HashSet::<&u8>::from_iter(l.as_bytes());
            candidates = candidates.intersection(&h2).copied().collect();
            println!("candidates = {:?}", candidates);
        }
        println!("{}", l);
    }

第二种解决方案是复制您的 l 字符串。

    let mut candidates = HashSet::<u8>::new();
    let mut sum = 0;
    for l in lines { // lines is Vec<String>
        if candidates.len()==0 {
            candidates = HashSet::<u8>::from_iter(l.clone().into_bytes());
            println!("candidates = {:?}", candidates);
        } else if l.len() == 0 {
            // end of group
            sum = sum + candidates.len();
            candidates = HashSet::<u8>::new();
        } else {
            let h2 = HashSet::<u8>::from_iter(l.clone().into_bytes());
            candidates = candidates.intersection(&h2).copied().collect();
            println!("candidates = {:?}", candidates);
        }
        println!("{}", l);
    }

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2021-09-26
    • 2014-11-27
    • 1970-01-01
    • 1970-01-01
    • 2023-02-05
    • 1970-01-01
    相关资源
    最近更新 更多